Temp/Barometer

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author
    Posts
  • #15396
    johnmark
    Participant

    My project team and I are having a hard time getting the BMP280 to return temperature and pressure data. (We really just want altitude). We are using the script from ozzmaker.com, found here:

    https://github.com/ozzmaker/BerryIMU/tree/master/python-BMP280-temperature-pressure

    When we run the script as-is, the following Error is returned

     

    File 'bmp280.py", line 85, in <module>

    p= (p - (var2/4096.0)) * 6250.0 /var1

    ZeroDivisionError: float division by zero

     

    Digging through the file, we have traced back var1 to the read from the temperature sensor, which is reading 0.

    We have also done due diligence with the hardware, and the connections are securely connected. Additionally, the GPS and IMU functions are working correctly.

     

    P.S. I apologize that this will be my second post in a couple days, we've been spending a lot of time hitting our heads against a wall with this module. We bought this module hoping for a one-stop-shop off-the-shelf solution to make it easy to dump GPS and 10DoF data into a CSV file but have found that integrating all the different scripts has been a lot more work than anticipated. Any help/direction to a script which maybe already does this would be greatly appreciated.

    #15399
    johnmark
    Participant

    Edit: Confirmed, the data returned from the command bus.read_i2c_block_data(0x77, 0x88, 24) is all zeros.

    b1 = bus.read_i2c_block_data(0x77, 0x88, 24)
    print(b1)
    > 0,0,0,0,0,0,0

    #15411
    PeterP
    Participant

    Can you check on the back of the PCB and see what version you have?  if you have version 3.5, then it would be using the BMP388.  Sorry for any confusion.

     

    Try the attached code.

     

    Peter --OzzMaker.com --

    #15429
    johnmark
    Participant

    Just looked on the back of the berryGPS-IMU board, and confirmed that it is, in fact, version 3.5.

    I do not see any code attached to your previous message? Could you resend link?

    #15432
    PeterP
    Participant
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import time
    import smbus
    import math
    
    # define BMP388 Device I2C address
    
    I2C_ADD_BMP388_AD0_LOW = 0x76
    I2C_ADD_BMP388_AD0_HIGH = 0x77
    I2C_ADD_BMP388 = I2C_ADD_BMP388_AD0_HIGH
    
    BMP388_REG_ADD_WIA = 0x00
    BMP388_REG_VAL_WIA = 0x50
    
    BMP388_REG_ADD_ERR = 0x02
    BMP388_REG_VAL_FATAL_ERR = 0x01
    BMP388_REG_VAL_CMD_ERR = 0x02
    BMP388_REG_VAL_CONF_ERR = 0x04
    
    BMP388_REG_ADD_STATUS = 0x03
    BMP388_REG_VAL_CMD_RDY = 0x10
    BMP388_REG_VAL_DRDY_PRESS = 0x20
    BMP388_REG_VAL_DRDY_TEMP = 0x40
    
    BMP388_REG_ADD_CMD = 0x7E
    BMP388_REG_VAL_EXTMODE_EN = 0x34
    BMP388_REG_VAL_FIFI_FLUSH = 0xB0
    BMP388_REG_VAL_SOFT_RESET = 0xB6
    
    BMP388_REG_ADD_PWR_CTRL = 0x1B
    BMP388_REG_VAL_PRESS_EN = 0x01
    BMP388_REG_VAL_TEMP_EN = 0x02
    BMP388_REG_VAL_NORMAL_MODE = 0x30
    
    BMP388_REG_ADD_PRESS_XLSB = 0x04
    BMP388_REG_ADD_PRESS_LSB = 0x05
    BMP388_REG_ADD_PRESS_MSB = 0x06
    BMP388_REG_ADD_TEMP_XLSB = 0x07
    BMP388_REG_ADD_TEMP_LSB = 0x08
    BMP388_REG_ADD_TEMP_MSB = 0x09
    
    BMP388_REG_ADD_T1_LSB = 0x31
    BMP388_REG_ADD_T1_MSB = 0x32
    BMP388_REG_ADD_T2_LSB = 0x33
    BMP388_REG_ADD_T2_MSB = 0x34
    BMP388_REG_ADD_T3 = 0x35
    BMP388_REG_ADD_P1_LSB = 0x36
    BMP388_REG_ADD_P1_MSB = 0x37
    BMP388_REG_ADD_P2_LSB = 0x38
    BMP388_REG_ADD_P2_MSB = 0x39
    BMP388_REG_ADD_P3 = 0x3A
    BMP388_REG_ADD_P4 = 0x3B
    BMP388_REG_ADD_P5_LSB = 0x3C
    BMP388_REG_ADD_P5_MSB = 0x3D
    BMP388_REG_ADD_P6_LSB = 0x3E
    BMP388_REG_ADD_P6_MSB = 0x3F
    BMP388_REG_ADD_P7 = 0x40
    BMP388_REG_ADD_P8 = 0x41
    BMP388_REG_ADD_P9_LSB = 0x42
    BMP388_REG_ADD_P9_MSB = 0x43
    BMP388_REG_ADD_P10 = 0x44
    BMP388_REG_ADD_P11 = 0x45
    
    class BMP388(object):
    
        """docstring for BMP388"""
    
        def __init__(self, address=I2C_ADD_BMP388):
            self._address = address
            self._bus = smbus.SMBus(0x01)
    
            # Load calibration values.
    
            if self._read_byte(BMP388_REG_ADD_WIA) == BMP388_REG_VAL_WIA:
                print("Pressure sersor is BMP388!\r\n")
                u8RegData = self._read_byte(BMP388_REG_ADD_STATUS)
                if u8RegData & BMP388_REG_VAL_CMD_RDY:
                    self._write_byte(BMP388_REG_ADD_CMD,
                                     BMP388_REG_VAL_SOFT_RESET)
                    time.sleep(0.01)
            else:
                print ("Pressure sersor NULL!\r\n")
            self._write_byte(BMP388_REG_ADD_PWR_CTRL,
                             BMP388_REG_VAL_PRESS_EN
                             | BMP388_REG_VAL_TEMP_EN
                             | BMP388_REG_VAL_NORMAL_MODE)
            self._load_calibration()
    
        def _read_byte(self, cmd):
            return self._bus.read_byte_data(self._address, cmd)
    
        def _read_s8(self, cmd):
            result = self._read_byte(cmd)
            if result > 128:
                result -= 256
            return result
    
        def _read_u16(self, cmd):
            LSB = self._bus.read_byte_data(self._address, cmd)
            MSB = self._bus.read_byte_data(self._address, cmd + 0x01)
            return (MSB << 0x08) + LSB
    
        def _read_s16(self, cmd):
            result = self._read_u16(cmd)
            if result > 32767:
                result -= 65536
            return result
    
        def _write_byte(self, cmd, val):
            self._bus.write_byte_data(self._address, cmd, val)
    
        def _load_calibration(self):
            print ("_load_calibration\r\n")
            self.T1 = self._read_u16(BMP388_REG_ADD_T1_LSB)
            self.T2 = self._read_u16(BMP388_REG_ADD_T2_LSB)
            self.T3 = self._read_s8(BMP388_REG_ADD_T3)
            self.P1 = self._read_s16(BMP388_REG_ADD_P1_LSB)
            self.P2 = self._read_s16(BMP388_REG_ADD_P2_LSB)
            self.P3 = self._read_s8(BMP388_REG_ADD_P3)
            self.P4 = self._read_s8(BMP388_REG_ADD_P4)
            self.P5 = self._read_u16(BMP388_REG_ADD_P5_LSB)
            self.P6 = self._read_u16(BMP388_REG_ADD_P6_LSB)
            self.P7 = self._read_s8(BMP388_REG_ADD_P7)
            self.P8 = self._read_s8(BMP388_REG_ADD_P8)
            self.P9 = self._read_s16(BMP388_REG_ADD_P9_LSB)
            self.P10 = self._read_s8(BMP388_REG_ADD_P10)
            self.P11 = self._read_s8(BMP388_REG_ADD_P11)
    
            # print(self.T1)
            # print(self.T2)
            # print(self.T3)
            # print(self.P1)
            # print(self.P2)
            # print(self.P3)
            # print(self.P4)
            # print(self.P5)
            # print(self.P6)
            # print(self.P7)
            # print(self.P8)
            # print(self.P9)
            # print(self.P10)
            # print(self.P11)
    
        def compensate_temperature(self, adc_T):
            partial_data1 = adc_T - 256 * self.T1
            partial_data2 = self.T2 * partial_data1
            partial_data3 = partial_data1 * partial_data1
            partial_data4 = partial_data3 * self.T3
            partial_data5 = partial_data2 * 262144 + partial_data4
            partial_data6 = partial_data5 / 4294967296
            self.T_fine = partial_data6
            comp_temp = partial_data6 * 25 / 16384
            return comp_temp
    
        def compensate_pressure(self, adc_P):
            partial_data1 = self.T_fine * self.T_fine
            partial_data2 = partial_data1 / 0x40
            partial_data3 = partial_data2 * self.T_fine / 256
            partial_data4 = self.P8 * partial_data3 / 0x20
            partial_data5 = self.P7 * partial_data1 * 0x10
            partial_data6 = self.P6 * self.T_fine * 4194304
            offset = self.P5 * 140737488355328 + partial_data4 \
                + partial_data5 + partial_data6
    
            partial_data2 = self.P4 * partial_data3 / 0x20
            partial_data4 = self.P3 * partial_data1 * 0x04
            partial_data5 = (self.P2 - 16384) * self.T_fine * 2097152
            sensitivity = (self.P1 - 16384) * 70368744177664 \
                + partial_data2 + partial_data4 + partial_data5
    
            partial_data1 = sensitivity / 16777216 * adc_P
            partial_data2 = self.P10 * self.T_fine
            partial_data3 = partial_data2 + 65536 * self.P9
            partial_data4 = partial_data3 * adc_P / 8192
            partial_data5 = partial_data4 * adc_P / 512
            partial_data6 = adc_P * adc_P
            partial_data2 = self.P11 * partial_data6 / 65536
            partial_data3 = partial_data2 * adc_P / 128
            partial_data4 = offset / 0x04 + partial_data1 + partial_data5 \
                + partial_data3
            comp_press = partial_data4 * 25 / 1099511627776
            return comp_press
    
        def get_temperature_and_pressure_and_altitude(self):
            """Returns pressure in Pa as double. Output value of "6386.2"equals 96386.2 Pa = 963.862 hPa."""
    
            xlsb = self._read_byte(BMP388_REG_ADD_TEMP_XLSB)
            lsb = self._read_byte(BMP388_REG_ADD_TEMP_LSB)
            msb = self._read_byte(BMP388_REG_ADD_TEMP_MSB)
            adc_T = (msb << 0x10) + (lsb << 0x08) + xlsb
            temperature = self.compensate_temperature(adc_T)
            xlsb = self._read_byte(BMP388_REG_ADD_PRESS_XLSB)
            lsb = self._read_byte(BMP388_REG_ADD_PRESS_LSB)
            msb = self._read_byte(BMP388_REG_ADD_PRESS_MSB)
    
            adc_P = (msb << 0x10) + (lsb << 0x08) + xlsb
            pressure = self.compensate_pressure(adc_P)
            altitude = 4433000 * (0x01 - pow(pressure / 100.0 / 101325.0,
                                  0.1903))
    
            return (temperature, pressure, altitude)
    
    if __name__ == '__main__':
    
     import time
     
     print("BMP388 Test Program ...\n")
     
     bmp388 = BMP388()
        
     while True:
      time.sleep(0.5)
      temperature,pressure,altitude = bmp388.get_temperature_and_pressure_and_altitude()
      print(' Temperature = %.1f Pressure = %.2f  Altitude =%.2f '%(temperature/100.0,pressure/100.0,altitude/100.0))

    Peter --OzzMaker.com --

    #15434
    johnmark
    Participant

    A partial success: We tabbed through the code, but got an error:

    AttributeError: 'BMP388' object has no attribute 'T1'.

    To us, it seemed like the function _load_calibration(): was never being called, so we added a line bmp388._load_calibration()  in to the  if __name__ = '__main__':  module. Edit for clarity, we added this line right after the line bmp388=BMP388() which declares the object.

    Now the program executes, but all the data is stale.

    Temperature = 23.7 Pressure = 79241.63 Altitude =2026.07

    Any thoughts?

     

    • This reply was modified 4 months, 3 weeks ago by johnmark.
    #15440
    johnmark
    Participant

    Solved:

    The code supplied above by Peter is correct. When copy-pasting, we lost indentations, and did not do it properly ourselves. The proper indentation must be used. Here is a link to a location that we found the same code, but with indents intact for the BerryGPS v3.5

    TLDR: Use this code for the BMP388 temp/pressure/altimeter

    https://github.com/getelectronics/PIBits/blob/master/python/bmp388.py

    Cheers, and thank you Peter for all the support.

    #15692
    jimb
    Participant

    Hi johnmark, I was happy to see your post....

    I am running your code from github with the BerryGPS-IMU but, I always get the message "Pressure sersor NULL!" followed by:

    Temperature = 0.0 Pressure = 0.0  Altitude =44330.00
    Temperature = 0.0 Pressure = 0.0  Altitude =44330.00
    Temperature = 0.0 Pressure = 0.0  Altitude =44330.00
    ....

    The GPS and IMU are both working as expected.

    Do you have an pointers based on your experience?

    Thank you!

    #15697
    johnmark
    Participant

    Here are some things that we checked

    • Check which berryGPS version ... it was found that we have the bmp388, rather than the bmp280. .
      • Per Peter's comment above, "Can you check on the back of the PCB and see what version you have?  if you have version 3.5, then it would be using the BMP388."
      • If you have the older version of the berryGPS, which has a bmp280, you will need different code, which can be found above in the first post on this thread.
    • Ensure that I2C is enabled under the raspi-config > interfaces menu, and that I2C is reading that register 0x77 is occupied  (as shown in the IMU guide here: https://ozzmaker.com/berryimu/

    Those would be my best guesses where to start based on our team's experience.
    Keep us updated and good luck.

    #15698
    jimb
    Participant

    Thank you very much for your kind reply. It turns out that indeed, I have a V2 BerryGPS-IMU so, when I use the BMP280 code everything runs as expected. Thank you again for your help.

Viewing 10 posts - 1 through 10 (of 10 total)
  • You must be logged in to reply to this topic.

Blip, blop, bloop...