Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 23:28 17 Feb 2026 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : BME280

Author Message
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 2039
Posted: 06:46am 16 Feb 2026
Copy link to clipboard 
Print this post

Here it is again....

I am trying to use a BME280 for Temperature and Humidity with this code from Peter..
option explicit
option default none
'
' BME280 routines and test harness
'
const BME280_ADDRESS = &H77
const BME280_REGISTER_T1 = &H88
const BME280_REGISTER_P1 = &H8E
const BME280_REGISTER_H1 = &HA1
const BME280_REGISTER_H2 = &HE1
const BME280_REGISTER_CHIPID = &HD0
const BME280_REGISTER_CONTROLHUMID = &HF2
const BME280_REGISTER_CONTROL = &HF4
const BME280_REGISTER_PRESSUREDATA = &HF7
const BME280_REGISTER_TEMPDATA = &HFA
const BME280_REGISTER_HUMIDDATA = &HFD
'
dim integer s16=&HFFFFFFFFFFFF0000 , s16b=&H8000
dim integer s12=&HFFFFFFFFFFFFF000 , s12b=&H800
dim integer s8= &HFFFFFFFFFFFFFF00 , s8b=&H80
'
DIM INTEGER T1,T2,T3 'uint16_t, int16_t, int16_t
DIM INTEGER P1,P2,P3,P4,P5,P6,P7,P8,P9 'uint16_t, 8 x int16_t
DIM INTEGER H1,H2,H3,H4,H5,H6 'uint8_t, int16_t , uint8_t, int16_t, int16_t, int8_t
'
dim INTEGER t_fine 'used to store accurate temp reading from temp conversion for use in pressure and humidity conversions
'
' Test program
'
bme280_init
do
print bme280_read_temp() 'must be run before pressure or humidity
print bme280_read_pressure()
print bme280_read_humidity()
pause 2000
loop
'
end
'
'***************************************************************************************************
'
function bme280_read_temp() as float
local integer var1,var2,adc_T
local adc%(2)
i2c write BME280_ADDRESS,1,1,BME280_REGISTER_TEMPDATA
i2c read BME280_ADDRESS,0,3,adc%()
adc_T=((adc%(0)<<16) OR (adc%(1)<<8) or adc%(2))>>4
var1 = ((((adc_T>>3) - (T1 <<1))) * T2) \ q(11)
var2 = (((((adc_T>>4) - (T1)) * ((adc_T\ q(4)) - (T1))) \ q(12)) * (T3)) \ q(14)
t_fine = var1 + var2
bme280_read_temp = ((t_fine * 5 + 128) \ q(8))/100.0
end function

function bme280_read_pressure() as float
local integer var1, var2, adc_P, p
local adc%(2)
i2c write BME280_ADDRESS,1,1,BME280_REGISTER_PRESSUREDATA
i2c read BME280_ADDRESS,0,3,adc%()
adc_P=((adc%(0)<<16) OR (adc%(1)<<8) or adc%(2))>>4
var1 = t_fine - 128000
var2 = var1 * var1 * P6
var2 = var2 + ((var1 * P5)<<17)
var2 = var2 + (P4 << 35)
var1 = ((var1 * var1 * P3)\ q(8)) + ((var1 * P2)<<12)
var1 = ((1<<47)+var1)*P1\ q(33)
if var1 = 0 THEN
bme280_read_pressure = 0' avoid exception caused by division by zero
exit function
endif
p = 1048576 - adc_P
p = (((p<<31) - var2)*3125) \ var1
var1 = (P9 * (p\ q(13)) * (p\ q(13))) \ q(25)
var2 = (P8 * p) \ q(19)
p = ((p + var1 + var2) \ q(8)) + (P7<<4)
bme280_read_pressure = p/25600.0
end function
'
function bme280_read_humidity() as float
local integer v_x1,adc_H
local adc%(1)
i2c write BME280_ADDRESS,1,1,BME280_REGISTER_HUMIDDATA
i2c read BME280_ADDRESS,0,2,adc%()
adc_H=(adc%(0)<<8) or adc%(1)
v_x1 = t_fine - 76800
v_x1=(((((adc_H<<14)-((H4)<<20)-(H5*v_x1))+16384)\ q(15))*(((((((v_x1*H6)\ q(10))*(((v_x1*H3)\ q(11))+32768))\ q(10))+2097152)*H2+8192)\ q(14)))
v_x1 = (v_x1 - (((((v_x1 \ q(15)) * (v_x1 \ q(15))) \ q(7)) * (H1)) \ q(4)))
if v_x1< 0 then v_x1 = 0
if v_x1 > 419430400 then v_x1= 419430400
bme280_read_humidity = (v_x1\ q(12)) / 1024.0
end function

sub bme280_init
local i%,cal%(17)
i2c open 400,1000 '400KHz bus speed
i2c write BME280_ADDRESS,1,1,BME280_REGISTER_CHIPID
i2c read BME280_ADDRESS,0,1,i%
if i%<>&H60 then print "Error BME280 not found"
'
i2c write BME280_ADDRESS,1,1,BME280_REGISTER_T1
i2c read BME280_ADDRESS,0,6,cal%()
T1=cal%(0) OR (cal%(1)<< 8)
T2=cal%(2) OR (cal%(3)<< 8): if T2 and s16b then T2=T2 OR s16 'sign extend if required
T3=cal%(4) OR (cal%(5)<< 8): if T3 and s16b then T3=T3 OR s16
'
i2c write BME280_ADDRESS,1,1,BME280_REGISTER_P1
i2c read BME280_ADDRESS,0,18,cal%()
P1=cal%(0) OR (cal%(1)<<8)
P2=cal%(2) OR (cal%(3)<<8): if P2 and s16b then P2=P2 OR s16 'sign extend if required
P3=cal%(4) OR (cal%(5)<<8): if P3 and s16b then P3=P3 OR s16
P4=cal%(6) OR (cal%(7)<<8): if P4 and s16b then P4=P4 OR s16
P5=cal%(8) OR (cal%(9)<<8): if P5 and s16b then P5=P5 OR s16
P6=cal%(10) OR (cal%(11)<<8): if P6 and s16b then P6=P6 OR s16
P7=cal%(12) OR (cal%(13)<<8): if P7 and s16b then P7=P7 OR s16
P8=cal%(14) OR (cal%(15)<<8): if P8 and s16b then P8=P8 OR s16
P9=cal%(16) OR (cal%(17)<<8): if P9 and s16b then P9=P9 OR s16
'
i2c write BME280_ADDRESS,1,1,BME280_REGISTER_H1
i2c read BME280_ADDRESS,0,1,H1
i2c write BME280_ADDRESS,1,1,BME280_REGISTER_H2
i2c read BME280_ADDRESS,0,7,cal%()
H2=cal%(0) OR (cal%(1)<< 8): if H2 and s16b then H2=H2 OR s16 'sign extend if required
H3=cal%(2)
H6=cal%(6): if H6 and s8b then H6=H6 OR s8 'sign extend if required
H4=(cal%(3)<<4) OR (cal%(4) and &H0F): if H4 and s12b then H4=H4 OR s12 'sign extend if required
H5=(cal%(5)<<4) OR (cal%(4)>>4): if H5 and s12b then H5=H5 OR s12
'
i2c write BME280_ADDRESS,0,2,BME280_REGISTER_CONTROLHUMID,&H05 '16x oversampling humidity
i2c write BME280_ADDRESS,0,2,BME280_REGISTER_CONTROL,&HB7 '16x oversampling pressure/temp, normal mode
'
end sub
'
function q(x as integer) as integer 'returns 2 raised to the power
q=(1<<x)
End CFunction


I had to comment out the last line "End Cfunction"
The program runs but at first I get an error "BME280 not found"  at line 98.
The program continues to run after this with correct Temperature and Pressure values but Humidity is 0.
The value of i% in line 98 is 88.
Edited 2026-02-16 15:54 by palcal
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 3013
Posted: 07:00am 16 Feb 2026
Copy link to clipboard 
Print this post

It's just a typo. Delete just the "C" from CFunction.
Function q(x as integer) as integer 'returns 2 raised to the power
  q=(1<<x)
End Function


The humidity function uses the q() function but without an End Function it never returns to the humidity function, hence you get zero.

Your original post is in "Windmills"

Here it is with indenting restored to make it more readable.
Also added a debug message to the error message in Sub bme280_init.
option explicit
option default none
'
' BME280 routines and test harness
'
const BME280_ADDRESS = &H77
const BME280_REGISTER_T1 = &H88
const BME280_REGISTER_P1 = &H8E
const BME280_REGISTER_H1 = &HA1
const BME280_REGISTER_H2 = &HE1
const BME280_REGISTER_CHIPID = &HD0
const BME280_REGISTER_CONTROLHUMID = &HF2
const BME280_REGISTER_CONTROL = &HF4
const BME280_REGISTER_PRESSUREDATA = &HF7
const BME280_REGISTER_TEMPDATA = &HFA
const BME280_REGISTER_HUMIDDATA = &HFD
'
dim integer s16=&HFFFFFFFFFFFF0000 , s16b=&H8000
dim integer s12=&HFFFFFFFFFFFFF000 , s12b=&H800
dim integer s8= &HFFFFFFFFFFFFFF00 , s8b=&H80
'
DIM INTEGER T1,T2,T3 'uint16_t, int16_t, int16_t
DIM INTEGER P1,P2,P3,P4,P5,P6,P7,P8,P9 'uint16_t, 8 x int16_t
DIM INTEGER H1,H2,H3,H4,H5,H6 'uint8_t, int16_t , uint8_t, int16_t, int16_t, int8_t
'
dim INTEGER t_fine 'used to store accurate temp reading from temp conversion for use in pressure and humidity conversions
'
' Test program
'
bme280_init
Do
  print bme280_read_temp() 'must be run before pressure or humidity
  print bme280_read_pressure()
  print bme280_read_humidity()
  pause 2000
Loop
'
end
'
'***************************************************************************************************
'
Function bme280_read_temp() as float
  local integer var1,var2,adc_T
  local adc%(2)
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_TEMPDATA
  i2c read BME280_ADDRESS,0,3,adc%()
  adc_T=((adc%(0)<<16) OR (adc%(1)<<8) or adc%(2))>>4
  var1 = ((((adc_T>>3) - (T1 <<1))) * T2) \ q(11)
  var2 = (((((adc_T>>4) - (T1)) * ((adc_T\ q(4)) - (T1))) \ q(12)) * (T3)) \ q(14)
  t_fine = var1 + var2
  bme280_read_temp = ((t_fine * 5 + 128) \ q(8))/100.0
End Function
'
Function bme280_read_pressure() as float
  local integer var1, var2, adc_P, p
  local adc%(2)
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_PRESSUREDATA
  i2c read BME280_ADDRESS,0,3,adc%()
  adc_P=((adc%(0)<<16) OR (adc%(1)<<8) or adc%(2))>>4
  var1 = t_fine - 128000
  var2 = var1 * var1 * P6
  var2 = var2 + ((var1 * P5)<<17)
  var2 = var2 + (P4 << 35)
  var1 = ((var1 * var1 * P3)\ q(8)) + ((var1 * P2)<<12)
  var1 = ((1<<47)+var1)*P1\ q(33)
  If var1 = 0 THEN
    bme280_read_pressure = 0' avoid exception caused by division by zero
    Exit Function
  Endif
  p = 1048576 - adc_P
  p = (((p<<31) - var2)*3125) \ var1
  var1 = (P9 * (p\ q(13)) * (p\ q(13))) \ q(25)
  var2 = (P8 * p) \ q(19)
  p = ((p + var1 + var2) \ q(8)) + (P7<<4)
  bme280_read_pressure = p/25600.0
End Function
'
Function bme280_read_humidity() as float
  local integer v_x1,adc_H
  local adc%(1)
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_HUMIDDATA
  i2c read BME280_ADDRESS,0,2,adc%()
  adc_H=(adc%(0)<<8) or adc%(1)
  v_x1 = t_fine - 76800
  v_x1=(((((adc_H<<14)-((H4)<<20)-(H5*v_x1))+16384)\ q(15))*(((((((v_x1*H6)\ q(10))*(((v_x1*H3)\ q(11))+32768))\ q(10))+2097152)*H2+8192)\ q(14)))
  v_x1 = (v_x1 - (((((v_x1 \ q(15)) * (v_x1 \ q(15))) \ q(7)) * (H1)) \ q(4)))
  if v_x1< 0 then v_x1 = 0
  if v_x1 > 419430400 then v_x1= 419430400
  bme280_read_humidity = (v_x1\ q(12)) / 1024.0
End Function
'
Sub bme280_init
  local i%,cal%(17)
  i2c open 400,1000 '400KHz bus speed
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_CHIPID
  i2c read BME280_ADDRESS,0,1,i%
  if i%<>&H60 then print "Error BME280 not found, i% should be $H60 but was &H";Hex%(i%,2)
'
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_T1
  i2c read BME280_ADDRESS,0,6,cal%()
  T1=cal%(0) OR (cal%(1)<< 8)
  T2=cal%(2) OR (cal%(3)<< 8): if T2 and s16b then T2=T2 OR s16 'sign extend if required
  T3=cal%(4) OR (cal%(5)<< 8): if T3 and s16b then T3=T3 OR s16
'
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_P1
  i2c read BME280_ADDRESS,0,18,cal%()
  P1=cal%(0) OR (cal%(1)<<8)
  P2=cal%(2) OR (cal%(3)<<8): if P2 and s16b then P2=P2 OR s16 'sign extend if required
  P3=cal%(4) OR (cal%(5)<<8): if P3 and s16b then P3=P3 OR s16
  P4=cal%(6) OR (cal%(7)<<8): if P4 and s16b then P4=P4 OR s16
  P5=cal%(8) OR (cal%(9)<<8): if P5 and s16b then P5=P5 OR s16
  P6=cal%(10) OR (cal%(11)<<8): if P6 and s16b then P6=P6 OR s16
  P7=cal%(12) OR (cal%(13)<<8): if P7 and s16b then P7=P7 OR s16
  P8=cal%(14) OR (cal%(15)<<8): if P8 and s16b then P8=P8 OR s16
  P9=cal%(16) OR (cal%(17)<<8): if P9 and s16b then P9=P9 OR s16
'
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_H1
  i2c read BME280_ADDRESS,0,1,H1
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_H2
  i2c read BME280_ADDRESS,0,7,cal%()
  H2=cal%(0) OR (cal%(1)<< 8): if H2 and s16b then H2=H2 OR s16 'sign extend if required
  H3=cal%(2)
  H6=cal%(6): if H6 and s8b then H6=H6 OR s8 'sign extend if required
  H4=(cal%(3)<<4) OR (cal%(4) and &H0F): if H4 and s12b then H4=H4 OR s12 'sign extend if required
  H5=(cal%(5)<<4) OR (cal%(4)>>4): if H5 and s12b then H5=H5 OR s12
'
  i2c write BME280_ADDRESS,0,2,BME280_REGISTER_CONTROLHUMID,&H05 '16x oversampling humidity
  i2c write BME280_ADDRESS,0,2,BME280_REGISTER_CONTROL,&HB7 '16x oversampling pressure/temp, normal mode
'
End Sub
'
Function q(x as integer) as integer 'returns 2 raised to the power
  q=(1<<x)
End Function

Edited 2026-02-16 17:59 by phil99
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 2039
Posted: 08:15am 16 Feb 2026
Copy link to clipboard 
Print this post

Thanks Phil.
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 3013
Posted: 11:32am 16 Feb 2026
Copy link to clipboard 
Print this post

There is a typo in my addition to the error message in Sub bme280_init.
Hex%(i%,2) should be Hex$(i%,2). Corrected line is the last one here:-
Sub bme280_init
 local i%,cal%(17)
 i2c open 400,1000 '400KHz bus speed
 i2c write BME280_ADDRESS,1,1,BME280_REGISTER_CHIPID
 i2c read BME280_ADDRESS,0,1,i%
 if i%<>&H60 then print "Error BME280 not found, i% should be $H60 but was &H";Hex$(i%,2)
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 2039
Posted: 08:19pm 16 Feb 2026
Copy link to clipboard 
Print this post

Can't understand what you mean  "Hex%(i%,2) should be Hex$(i%,2). Corrected line is the last one here:-"
I can't find  Hex%(i%,2)  or  Hex$(i%,2)    is Hex$ a typo.

I used the code you posted but same result, I still get ERROR BME280 not found and humidity is zero
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4241
Posted: 08:42pm 16 Feb 2026
Copy link to clipboard 
Print this post

  palcal said  Can't understand what you mean  "Hex%(i%,2) should be Hex$(i%,2). Corrected line is the last one here:-"
I can't find  Hex%(i%,2)  or  Hex$(i%,2)    is Hex$ a typo.

I used the code you posted but same result, I still get ERROR BME280 not found and humidity is zero

After the line
Sub bme280_init

is an If and very near its end is Hex% which should be Hex$

John
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 3013
Posted: 08:50pm 16 Feb 2026
Copy link to clipboard 
Print this post

Hex$(i%,2) just formats the printout of i% in hexadecimal to correspond with the format in the program.
eg.
> i%=15
> ? "&H";Hex$(i%,2)
&H0F
>


Sub bme280_init reads the value of i% from the BME280 and expects to see a value of &H60.

i2c read BME280_ADDRESS,0,1,i%

If it does not get that it gives the error message.

if i%<>&H60 then print "Error BME280 not found, i% should be $H60 but was &H";Hex$(i%,2)

The bit I added shows what the actual value of i% is.
I don't have a BME280 so can't test it myself. If you run it again and post the value of i% I will have a look at the datasheet to see what it means.


Edit.
The datasheet is 60 pages!
It will take me several days to work through it, perhaps Peter can produce an answer quicker.
Edited 2026-02-17 07:06 by phil99
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6455
Posted: 09:12pm 16 Feb 2026
Copy link to clipboard 
Print this post

You have a BMP280
not a BME280

Chip ID for the BMP280 is 88 decimal = &h58
The BMP280 uses the same registers for temperature and pressure which is why you are getting readings for those.

Jim



Edited 2026-02-17 07:14 by TassyJim
VK7JH
MMedit
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 2039
Posted: 09:52pm 16 Feb 2026
Copy link to clipboard 
Print this post

  Quote  Chip ID for the BMP280 is 88 decimal = &h58

That is the value I get in the error message.
I still don't know what to do to fix it.  I bought the sensors as BME280, I can't take a picture because I can't find the memory card for my camera but the markings in the module are...
  GY-BM
   E/P
   280
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6455
Posted: 10:16pm 16 Feb 2026
Copy link to clipboard 
Print this post

  Quote  GY-BM
  E/P
  280

The same board is used for both chips.
If you are lucky, there will be a mark crossing out the E or the P.
The question is then, does crossing it out mean it is a P an E.
The actual chip do look different.

search for "bmp280 vs bme280"
VK7JH
MMedit
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 2039
Posted: 10:28pm 16 Feb 2026
Copy link to clipboard 
Print this post

OK it says BMP280 does not measure humidity. so look for BME280.
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 3013
Posted: 10:46pm 16 Feb 2026
Copy link to clipboard 
Print this post

The type number should be engraved on the tiny metal box.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6455
Posted: 11:07pm 16 Feb 2026
Copy link to clipboard 
Print this post



Or with batch markings:
  Quote  This is the smoking gun. If you look at the BME280 datasheet, on Page 44, the markings for mass production devices is shown. The marking should be in the format ??? U? where the U indicates BME280. The final ? is only a P according to this revision of the datasheet as there is only one subcontractor, so the last two characters should be UP.

Comparing this with the BMP280 datasheet, on Page 41, the format should be ??? K?, where the last ? is either P, U, N, W. Thus KP, KU, KN, KW are all BMP280 devices.


Jim
VK7JH
MMedit
 
palcal

Guru

Joined: 12/10/2011
Location: Australia
Posts: 2039
Posted: 12:24am 17 Feb 2026
Copy link to clipboard 
Print this post

Thanks for that.
Mine is KU so it is a BMP280.
Edited 2026-02-17 10:53 by palcal
"It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all"
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2026