March 12, 2020 at 1:54 am #15396
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:
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.March 12, 2020 at 4:53 am #15399
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)
> 0,0,0,0,0,0,0March 12, 2020 at 12:50 pm #15411PeterPParticipant
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 --March 13, 2020 at 12:34 am #15429
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?March 13, 2020 at 12:40 am #15432PeterPParticipant
#!/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 --March 13, 2020 at 1:02 am #15434
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
March 13, 2020 at 5:05 am #15440
- This reply was modified 4 months, 3 weeks ago by johnmark.
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
Cheers, and thank you Peter for all the support.March 27, 2020 at 8:40 am #15692jimbParticipant
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!March 28, 2020 at 1:00 am #15697
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.March 28, 2020 at 1:37 am #15698jimbParticipant
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.
- You must be logged in to reply to this topic.