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 : MM2(+): BME280 temp, pressure, humidity
Author | Message | ||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9110 |
This device is certainly useful but what a ridiculous programming interface The registers where you read the conversion data are big-endian. However, the registers where you read the calibration data are little-endian. What plonker thought that one up? Moreover, the humidity function has two calibration data elements sharing registers in a most bizarre way. Finally there is a gotcha that may affect any port from C to MMBasic. In MMBasic the ">>" operator always puts a zero into the 64th bit. In C, if the datatype is signed then ">>" will put a zero or 1 depending on whether the number was originally positive or negative However, having sorted all that out here is a program for reading the temperature, pressure and humidity from a BME280 (thanks to lew247 for the loan of the module) Connection to the device is I2C. Connect I2C Clock on the Micromite to SCK on the module Connect I2C Data on the Micromite to SDI on the module Connect power and ground (the device works fine on 3.3V) Leave CS and SDO on the module unconnected UPDATE - Removed CFunctions so now Basic only 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 |
||||
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
Thank you so much for this |
||||
viscomjim Guru Joined: 08/01/2014 Location: United StatesPosts: 925 |
Matherp... you are a machine! Do you dream in code? Amazing stuff here.... |
||||
centrex Guru Joined: 13/11/2011 Location: AustraliaPosts: 320 |
Hi Matherp Way above my pay scale but how accurate is the device with the readings you have obtained????? Cliff Cliff |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9110 |
Difficult to say - it is certainly very stable. The code sets the device for 16x oversampling on all measurements Humidity measurements were within 2% of DHT22, temperature measurements within 1 degree of DS18B20. |
||||
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
Probably asking too much but is there an easy way to display altitude? I can see how it's done on the BME280 on the arduino code but thats like speaking a totally foreign language to me |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9110 |
See this thread for code and discussion. You can't properly calculate altitude without knowing sea level pressure at the same time and even then you are basing it on a model of the atmosphere which may not be exact at that particular moment. However the thread contains simple code for converting local pressure to altitude given sea level pressure. If you don't know sea-level pressure then 1013.25 is considered "standard". Aircraft above a certain altitude all set 1013.25 as the notional sea-level pressure. This way if they fly 1000ft apart in altitude then they will be at that separation even though the absolute altitude may be different to that displayed on their altimeters |
||||
v.lenzer Regular Member Joined: 04/05/2024 Location: GermanyPosts: 49 |
I need your help again. I want to build a display for temperature, air pressure and humidity using an RP2040-Zero, a BME/BMP280-I2C module and a TFT ILI9341. I was happy when I found the MMBasic source here. As far as I understand, the program runs on a Micromite MM2. The I2C device is labeled "BME/BMP280". It has the inputs GND, Vin, SCL and SDA. The device address is hex76/dec118. This address was recognized by an I2C scanner. So it should work. The RP2040-Zero has the MMBasic version 5.09.00RC5. I have adapted the program, which should initially only output the values on the console: SETPIN GP0,GP01,I2C const BME280_ADDRESS = &H76 I have not set any options. After RUN there is no error message, but no measured values appear either. I have built text output into the bme280_init function. That is how I know that it is called. The error "Error BME280 not found" is not output - the device has obviously been recognized. The value for i% is dez96. The program then also enters the do/loop loop, but the functions bme280_read_temp() bme280_read_pressure() bme280_read_humidity() are not called and the pause of 2 seconds is not processed. The loop is also exited. Does anyone have any idea why this might be. Edited 2024-06-27 02:45 by v.lenzer Best wishes! Joachim |
||||
v.lenzer Regular Member Joined: 04/05/2024 Location: GermanyPosts: 49 |
I just found the error: The last line in the above program is wrong! It should say: "END FUNCTION" and not "END CFUNCTION" Now I get all the values I want. Thanks for the program!! Best wishes! Joachim |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2135 |
Indeed! Perhaps it was designed on April 1, or by a disgruntled employee on their last day with the firm. For comparison the Sub for an AHT10, no pressure sensing but still... Sub AHT10 Local dat(4) as Integer I2C read AHaddr,1,5,dat() 'read first 5 data bytes - last one not needed. humid = Cint(dat(1) / 2.56) temp = Cint((((dat(3) And 15) << 8) + dat(4)) / 2.048 - 500) / 10 I2C write AHaddr, 0, 3, 172, 51, 0 'trigger measurement for next read End Sub Edited 2024-06-27 14:19 by phil99 |
||||
Print this page |