logo elektroda
logo elektroda
X
logo elektroda

[Solved] [lua] BME280 - How to correctly read the temperature from registers 0xFA-0xFC?

czasnagli 4335 49
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
  • #1 17037114
    czasnagli
    Level 17  
    Welcome!

    I want to read the temperature from the BME280 in a lua script. In datasheets I read that the temperature is stored at 0xFA , 0xFB and 0xFC .

    [lua] BME280 - How to correctly read the temperature from registers 0xFA-0xFC? .

    After reading these addresses with the command
    Code: Lua
    Log in, to see the code
    .
    I received 128 , 0 and 0 respectively.
    Code: Lua
    Log in, to see the code
    .

    I know that the read value 128 is not the temperature. I therefore have a question. How is the temperature read out?
  • ADVERTISEMENT
  • #2 17037150
    chemik22
    Level 14  
    And do you specify the device address somewhere in your code ? As a rule, the BME280 can have two different addresses (0x77 and 0x76) depending on the configuration. Although in most cases "Chinese" boards with this module are prepared in such a way that they have the address 0x76 probably

    Added after 3 [minutes]:



    Also, I can't remember exactly but I think you have to write something to one of the config registers before the first read to determine the sensor mode. Check the documentation...
  • #3 17037788
    czasnagli
    Level 17  
    chemik22 wrote:
    Are you specifying the device address somewhere in your code ?
    .
    This is how I specify the device address 0x76 which is correct. At address 0x77 , there is a reset so it is not correct.

    chemik22 wrote:
    I don't remember exactly either, but I think before the first read you have to write something to one of the config registers to determine the sensor mode. Check in the documentation...
    .

    I also think you need to set the bits before the first read. The problem is that so far I haven't found information about which settings exactly. In config 0xF5 I set in t_sb[2:0] different bits, but this did not help.

    I also set in 0xF4 Mode . Normal mode 0x03 , but the reading has not changed. I don't know if the write of the configuration bits is done only once or with each read. I am running out of ideas already.

    Code: Lua
    Log in, to see the code
    .
  • Helpful post
    #4 17038852
    chemik22
    Level 14  
    It appears that with this configuration it should work without any problem. The best thing to do is to check with a logic analyzer (you can buy one for a few zlotys) what is really happening on the data lines. Because it is difficult to find out what these functions actually do (io.write... etc.).


    I have configured my AVR like this:


    (the order of configuration from what I recall matters)
    0xF2 as: 0b00000001 // x1
    0xF4 as: 0b00100101 // temp 001 x1, pressure 001 x1; mode normal 11, forced 01
    0xF5 as: 0b000000 // t_sb (000) 0.5ms



    In my case it was forced mode, i.e. every time 0xF4 is written to the register, a measurement takes place. If you want continuous measurement (normal mode) then give 0xF4 as: 0b00100111.
  • ADVERTISEMENT
  • #5 17039962
    czasnagli
    Level 17  
    chemik22 , I set the bits like you and I can already read the temperature from address 0xFA and 0xFB . From address 0xFC the temperature reading is always 0.

    Furthermore, I noticed that the BME280 shows a temperature of 123 . This is as much as 7°C less than the temperature read at the same time from the room thermometer (19°C). Should the temperature reading 123 from 0xFA be corrected or converted to °C? If I touch the sensor on the BME280 with my hand the temperature rises, but very slowly. From this I conclude that the thermometer is working, but the value of the temperature reading is not correct.
  • #6 17041170
    chemik22
    Level 14  
    Unfortunately, the conversion of the measurement value into a virulent format is not so obvious here. You can find the entire algorithm in the documentation: https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf

    on page 23 it says how to convert it. Unfortunately you have to adapt it to your own code. Well, unless you use Arduino where the "get temp" command magically gives you the result after a wake-up call.... but that's the nature of Arduino...
  • ADVERTISEMENT
  • #7 17041841
    czasnagli
    Level 17  
    chemik22 wrote:
    You have the entire algorithm in the documentation: https://cdn-shop.adafruit.com/datasheets/BST-BME280 DS001-10.pdf

    On page 23 it says how to convert it.
    .

    I will then use the example on page 23 to calculate the temperature. The temperature dig_T1 , dig_T2 and dig_T3 I read from the addresses:
    - dig_T1 = 0x88/0x89,
    - dig_T2 = 0x8A/0x8B,
    - dig_T3 = 0x8C/0x8D
    .

    You will also need the value adc_T for the calculation. Can you suggest where to read the value adc_T ?

    [lua] BME280 - How to correctly read the temperature from registers 0xFA-0xFC? .
  • #8 17041999
    chemik22
    Level 14  
    The adc_T is your value read from the 0xFA-FC registers but written together as a 24bit number. I'll give you here a snippet of my old code I found that implemented these equations for the AVR. I think you should find it relatively easy to make a translation for your needs:

    Code: C / C++
    Log in, to see the code
    .

    Added after 6 [minutes]:

    And one more thing. These dig_T1 etc values are calibration data. You can safely read them once in the terminal and enter them openly. They are set once at the production stage of the device and do not change. I even remember somewhere on the internet that they were stated as "usually".
  • #9 17043560
    czasnagli
    Level 17  
    Based on what you have written I did as follows. From the address 0x88 and . 0x89 I read the value of dig_T1 .
    Code: Lua
    Log in, to see the code
    .

    I then added up the values from address 0x88 and 0x89 .
    Code: Lua
    Log in, to see the code
    .

    After summing the value dig_T1 = 11101101 .
    Did I correctly calculate the calibration value dig_T1 ?

    In your example there is also a bit shift <<8 , but I did not do it.

    All the calibration values for temperature that I have read look like this.
    Code: Lua
    Log in, to see the code
    .
  • #10 17044031
    chemik22
    Level 14  
    You need to do a bit shift or read the value from 0x88 and 0x89 as a whole in one go because these two registers together form a 16bit number. Each dig_T1/2/3 is a 16bit number and not an 8bit number

    Added after 1 [hour] 21 [minutes]:



    If you have a bit shift problem in this Lua then take a regular calculator in Windows and convert the read register values (binary) to a Dec value for yourself and use that value "explicitly" in your code without reading every time. I see that dig_T1 is actually the number 27877 and I remember there was something about that value, so recalculate the others and use those values entered "offhand" and it will work
  • #11 17045841
    czasnagli
    Level 17  
    I have calculated the dig_T1/2/3 values.
    Code: Lua
    Log in, to see the code
    .

    Same values from BMP280-Arduino-Library https://github.com/mahfuz195/BMP280-Arduino-Library/blob/master/BMP280.cpp
    Code: Lua
    Log in, to see the code


    My readout calibration values for temperature.
    Code: Lua
    Log in, to see the code
    .

    Why does my calibration value for dig_T3 (50) differ so much from the dig_T3 = -1000.0 from the arduino library?


    EDIT: .

    Do we combine the read 8 bit temperature values into a 24 bit number in that order?
    Code: Lua
    Log in, to see the code
    .
  • #12 17046251
    chemik22
    Level 14  
    The order of combining the numbers is ok. Let us know if you eventually managed to see the actual temperature ;) .


    And why does dig_T3 have such a difference.... Probably because you have a BME280 and the library is for a BMP280. Slightly different layout then the values are probably different too.
  • ADVERTISEMENT
  • #13 17046887
    czasnagli
    Level 17  
    chemik22 wrote:
    Let us know if you finally managed to see the actual temperature ;)
    .
    I will write how in lua 8 bit dig_T1/2/3 values will be combined into a 24 bit number. :wink:
  • #14 17047117
    chemik22
    Level 14  
    I know this combining like a horse uphill.... ;) Usually when you want to do such a procedure it's one line but in Lua it can be a challenge so good luck :)


    You can also work around this and treat bit shifts as multiplication or division by 2*n i.e. for example: <<3 is equivalent to multiplying the result by 8
  • #15 17048600
    czasnagli
    Level 17  
    chemik22 wrote:
    Normally when you want to do such a procedure it is one line
    .
    Can you give an example in c of how to combine 8 bit values into a 24 bit number? In lua and Air200 theoretically some bitwise operations work, but I haven't tested them yet.
    Code: Lua
    Log in, to see the code
  • #16 17048750
    chemik22
    Level 14  
    czasnagli wrote:
    Can you give an example in c of how to combine 8 bit values into a 24 bit number?
    .




    Exactly right:

    BME_temp = ((BME_temp_MSB<<16) | (BME_temp_LSB<<8) | BME_temp_XLSB);


    Of course, BME_temp should be of type e.g. uint32_t so as to accommodate a 24bit number.
  • #17 17051710
    czasnagli
    Level 17  
    I have mastered the bit shifts and values dig_T1 , dig_T2 , dig_T3 and adc_T while the programme is running are calculated correctly. However, the calculated temperature value T is not correct (36930). I have marked the temperature T with a blue box. The calculations for var1, var2, t_fine and T I did as shown below.

    [lua] BME280 - How to correctly read the temperature from registers 0xFA-0xFC? .



    EDIT: .

    I found on this page https://github.com/vsky279/BME280/blob/master/bme280.lua that an additional parameter self is used to calculate the temperature in the function. I calculated the final temperature T without using the additional function just based on the actions you see above. In your opinion, is it necessary to use a separate function with additional parament self to calculate the final temperature?

    [lua] BME280 - How to correctly read the temperature from registers 0xFA-0xFC? .
  • #18 17052604
    chemik22
    Level 14  
    I would risk the extra self parameter. Or even copy what is alive on github. Certain things are such a "black box", perhaps there is a trick there without which you get a meaningless result.


    Ps.
    You can also count even with a Windows calculator and Excel what "final" temperature you get using the dig_T and adc_T values you read at the beginning. You will then see whether the error lies in this formula calculating the final temperature or perhaps already at the stage of reading dig_T and adc_T, which I think is less likely but it is worth ruling out this possibility.
  • #19 17052673
    czasnagli
    Level 17  
    I cannot copy the script from github alive because it is written in lua for esp. I also write in lua only under the Air200 gsm module. The problem is that many functions from esp are not compatible with those from Air200. I tried adding the parameter self to the function, but that didn't help. Will try to calculate the final temperature on foot.

    EDIT: .

    In this script https://github.com/vsky279/BME280/blob/master/bme280.lua when calculating the value of dig_T1 only the reading from address 0x88 . The address 0x89 is omitted.

    When calculating the value of adc_T only the reading from address 0xFA is taken into account. The address 0xFB and 0xFC is omitted.

    EDIT1: .

    After I warm up the sensor by hand and then let go of it, the calculated temperature goes from a 4 digit value to a 3 digit value and finally a 5 digit value. Doesn't any of the registers need to be cleared before or after reading the temperature?
  • #20 17053103
    chemik22
    Level 14  
    I don't know what the github script is about, but I did my maths exactly as I wrote in post #8 and didn't skip any registers and the result was ok. I think you can adapt the algorithm to yourself (it was on an AVR) and it should work.

    Added after 4 [minutes]: .



    The registers update themselves according to the configuration (normal mode/forced mode) and do not need to be manually deleted. The fact that after heating by hand the adc_T number decreases may be so, because the temperature calculation algorithm is not a linear function of the type y = ax +b and as adc_T increases, T does not necessarily increase.

    Added after 7 [minutes]:



    I always read in forced mode i.e. after writing to register 0xF4 as: 0b00100101 the temperature is read and this value sits in the adc_T register until the 0xF4 register is written to again.
  • #21 17053351
    czasnagli
    Level 17  
    chemik22 wrote:
    I think you can adapt the algorithm to yourself (he was on an AVR) and it should run
    .
    I have a script written based exactly on this algorithm.
    chemik22 wrote:
    I always read in forced mode i.e. after writing to register 0xF4 as: 0b00100101 the temperature is read and this value sits in the adc_T register until the 0xF4 register is written to again.
    .
    I also do this

    What puzzles me is the reading from the register temp_xlsb, which is always 0 . The pressure-dependent temperature is probably read from this register. I did not set the pressure reading configuration as I do not read it. Could a zero reading from register temp_xlsb, be the reason for the incorrect final temperature?
    Code: Lua
    Log in, to see the code
  • #22 17053451
    JacekCz
    Level 42  
    I've done my homework.
    Code: Lua
    Log in, to see the code
    .
    of which the result is
    Code: Text
    Log in, to see the code
    which translates to
    Code: Text
    Log in, to see the code
    .

    Maybe let's not doctor ourselves on something that language has always provided. I'm a bit surprised that a library is being used for shifting.
    I'm rooting for it, but juz I can't read myself in this thread. It's hard to get results when nothing including arithmetic is certain

    Aha, that's the result from a PC. Lua 5.3 .
    In this version, the integer type appears (as opposed to the default numeric type usually implemented as double)
  • Helpful post
    #23 17053453
    chemik22
    Level 14  
    The fact that they are zeros is hard for me to say if it matters but I certainly wouldn't assume it's just for the pressure measurement. Maybe it just hasn't come together for you yet so that there is something other than a zero there.


    One issue is that when you put the number together from temp_msb, temp_lsb, temp_xlsb, into a whole then you shift everything 4 bits to the right so that you get the correct value. Remember that the first four bits in temp_xlsb are always zeros and they don't change whereas you need to do this:


    BME_temp = ((BME_temp_MSB<<16) | (BME_temp_LSB<<8) | BME_temp_XLSB);
    BME_temp = (BME_temp>>4);
    BME_temp_int = (uint32_t)BME_temp;


    I am referring to this second line! You have to make it. It is very important to move everything together by:
    >> 4, I don't seem to see this offset in your code and it was in my post #8


    Alternatively you could also do:
    BME_temp = ((BME_temp_MSB<<12) | (BME_temp_LSB<<4) | BME_temp_XLSB >>4);


    This resulting number is a uint32_t i.e. without sign and this is your adc_T.... maybe from that you get results from space that you didn't shift >>4 ?
  • #24 17054090
    czasnagli
    Level 17  
    JacekCz wrote:
    I am a bit surprised that a library is used for shifting.
    .
    I have lua version 5.2 and your way does not work for me.

    [lua] BME280 - How to correctly read the temperature from registers 0xFA-0xFC?

    chemik22 wrote:
    .
    I mean that second line! You have to make it. It is very important to move everything together by:
    >> 4, I don't seem to see this offset in your code and it was in my post #8
    .
    You're right this offset I didn't do before because I didn't notice in post #8 the slider that hid outside the monitor. Because of this, I didn't notice the code that was below. After I added the offset >> 4 then the temperature reading is correct. Thank you very much for your help. :) .

    [lua] BME280 - How to correctly read the temperature from registers 0xFA-0xFC? .
  • #25 17054172
    JacekCz
    Level 42  
    czasnagli wrote:
    JacekCz wrote:
    I'm a bit surprised that a library is used for shifting.
    .
    I have lua version 5.2 and your way doesn't work for me.


    Aaaa, something would add up.

    I don't think there are offset operators in the official documentation in 5.2. I was under the mistaken impression that they had "always been there".
    Officially, the functions given are
    bit32.lshift (x, disp) and similar

    My fragment on PC-based Lua 5.2

    Code: Lua
    Log in, to see the code
    .

    The result is the same.
  • #26 17055021
    chemik22
    Level 14  
    czasnagli wrote:
    You're right this offset I didn't do before because I didn't notice in post #8 the slider that hid outside the monitor. For this reason, I didn't weigh the code below. After I added the offset >> 4 then the temperature reading is correct. Thank you very much for your help.
    .


    Most of my errors consist of forgetting something "small" ;) . Glad to see that in the end everything works as you wanted ;) .
  • #27 17055520
    czasnagli
    Level 17  
    I am now taking a pressure reading. The values dig_P1/dig_P9 and adc_P I have calculated the identically as dig_T1/dig_T1 and adc_T , but this time already with a bit shift > 4 . In view of this, I have these questions.
    Should I configure the registers before reading the pressure? Or leave it as it is now? At the moment I have the configuration you gave in post #4.
  • #28 17056027
    chemik22
    Level 14  
    As I stated in post #4 is cool for T/P/H reading without oversampling. Nothing else needs to be set up. You should get the pressure after the conversions. Unfortunately here the algorithm is a bit more elaborate because a lot of these parameters dig_ P 1-9

    Added after 2 [minutes]: .



    Well, and remember that for the pressure conversion you use the t_fine value and not the final temperature T
  • #29 17057894
    czasnagli
    Level 17  
    With the pressure I also get an incorrect result (about 740 hPa). I did the calculation on 32 bit variables ( BME280_S32_t and BME280_U32_t ).

    [lua] BME280 - How to correctly read the temperature from registers 0xFA-0xFC? .
    Code: Lua
    Log in, to see the code
    .
    EDIT: .

    The moisture reading is also wrong and brings " 0 ". I checked that the value v_x1_u32r is a negative number -548524057 .

    EDIT: .

    I have removed unnecessary ballast from the post as the humidity reading is already working correctly.
  • #30 17058737
    chemik22
    Level 14  
    czasnagli wrote:
    I have checked that the value of v_x1_u32r is a negative number -548524057.
    .


    This looks to me like some kind of overrun of the allowed value of the variable. Note that some parameters are even 64 bit some are u_int and others are int and maybe something is wrong with it that you are writing e.g. a u_int value to a variable declared as int or vice versa. Study the datasheet and see if you are sure you have the "variable ranges" as they should be....

Topic summary

The discussion addresses how to correctly read and convert temperature data from the BME280 sensor registers 0xFA to 0xFC using Lua scripting. Initial attempts to read raw bytes directly from these registers yielded incorrect temperature values. It was clarified that the BME280 requires proper device addressing (commonly 0x76 or 0x77) and configuration of control registers (0xF4, 0xF5) to set measurement modes before reading sensor data. The temperature raw data (adc_T) is a 20-bit value formed by combining the three registers (MSB, LSB, XLSB) and right-shifting by 4 bits. Calibration parameters dig_T1, dig_T2, and dig_T3 must be read from registers 0x88 to 0x8D as 16-bit values with correct bit-shifting and sign handling. The temperature calculation follows the algorithm detailed on page 23 of the BME280 datasheet, involving intermediate variables var1, var2, and t_fine. Lua's limited bitwise operation support (especially in version 5.2) requires using bit32 or external libraries for shifts and logical operations. For humidity and pressure readings, similar calibration and combination of registers apply, with humidity calibration values (dig_H4, dig_H5) stored in split registers (0xE4 to 0xE6) requiring careful bit masking and shifting. Issues with humidity calculation below 15°C were resolved by using arithmetic right shifts (bit.arshift) for signed values instead of logical right shifts (bit.rshift). Pressure calculation is complicated by 64-bit arithmetic requirements, which Lua 5.2 cannot natively handle, causing overflow problems. The discussion includes code snippets and references to Arduino libraries and GitHub Lua implementations, emphasizing the need to adapt algorithms carefully for the Lua environment and hardware specifics like the Air200 GSM module. The final solution involves correct register addressing, configuration, bitwise data assembly, calibration parameter reading, and application of the datasheet's compensation formulas with attention to Lua's bitwise operation limitations.
Summary generated by the language model.
ADVERTISEMENT