BMP085 Revisited...
zlantz
Posts: 136
So I have purchased a few BMP180 Module's (the new version of the BMP085), which have the same exact coding structure as the BMP085. I had problems before with i2c and have since gotten other i2c devices working. I can obtain the address of the BMP from an i2cscan and if I try to get the EEPROM values with the wrong address, the data comes back as -1. With the correct address it returns set values for the eeprom, which I understand is what it should do.
When I try to get pressure or temp data from it, I have to read to the write address $EE, which gives a bouncy reading that "appears" correct, at first glance. But is not. And if you use the address the Datasheet says (0xEF (read) and 0xEE (write)) the returned data is -1.
The pressure data changes, but not to pressure changes (blowing onto sensor).
The temp data changes, it climbs, but gets to a point then starts back over at 1, gets to that point again & repeats. (holding the sensor in my hand)
neither data's really settle at a consistent point.
This is what I am using to test the sensor with:
Which I have had similar luck with:
However, of these 2 codes, I should get the same resulting values, but I dont, as you can see below.
When I try to get pressure or temp data from it, I have to read to the write address $EE, which gives a bouncy reading that "appears" correct, at first glance. But is not. And if you use the address the Datasheet says (0xEF (read) and 0xEE (write)) the returned data is -1.
The pressure data changes, but not to pressure changes (blowing onto sensor).
The temp data changes, it climbs, but gets to a point then starts back over at 1, gets to that point again & repeats. (holding the sensor in my hand)
neither data's really settle at a consistent point.
This is what I am using to test the sensor with:
CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 ' $AA = 1010_1010 ' $77 = 0111_0111 ' $EE = 1110_1110 'BMP_Addr = $EE 'BMP_Addr = $77 'BMP_Addr = %1110_1110 'BMP_Addr = %1110_1111 'BMP_Addr = 10_1110 ' BMP-085 / BMP-180 Datasheet: 0xEF (read) and 0xEE (write) BMP_Read = $EE 'BMP_Write = $77 BMP_Write = $EE 'BMP_Write = $EF BMPSCL = 12 BMPSDA = 13 Var word AC1,AC2,AC3,AC4,AC5,AC6,B1,B2,MB,MC,MD 'E2Prom variables from BMP085 long UT, UP OBj I2C : "Basic_I2C_Driver_1.3" 'By Michael Green PST : "Parallax Serial Terminal" 'By Jeff Martin, Andy Lindsay, Chip Gracey PUB Main | mode, MSB, LSB, XLSB PST.Start(115_200) 'Sets BaudRate for PST. PST.Clear 'Clears PST Screen. I2C.Initialize(BMPSCL) I2C.Start(BMPSCL) repeat 'I2C.ReadWord(BMPSCL, BMP_Addr, I2C#OneAddr|$AA) AC1 := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$AA) AC2 := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$AC) ac3 := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$AE) ac4 := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$B0) ac5 := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$B2) ac6 := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$B4) b1 := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$B6) b2 := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$B8) mb := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$BA) mc := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$BC) md := I2C.ReadWord(BMPSCL, BMP_Read, I2C#OneAddr|$BE) ' // Read Temperature I2C.WriteByte(BMPSCL, BMP_Write, $F4|I2C#OneAddr, $2E) waitcnt ((clkfreq / 220) + cnt) ' Pause 4.5 mS UT := I2C.ReadWord(BMPSCL, BMP_Read, $F6|I2C#OneAddr) ' // Read Pressure mode := 3 I2C.WriteByte(BMPSCL, BMP_Write, $F4|I2C#OneAddr, $34|(mode<<6)) waitcnt ((clkfreq / 38) + cnt) ' Pause 26 mS MSB := I2C.ReadByte(BMPSCL, BMP_Read, $F6|I2C#OneAddr) LSB := I2C.ReadByte(BMPSCL, BMP_Read, $F7|I2C#OneAddr) XLSB := I2C.ReadByte(BMPSCL, BMP_Read, $F8|I2C#OneAddr) UP := (MSB<<16 + LSB<<8 + XLSB)>> (8 - mode) PST.NewLine PST.Dec(UT) PST.NewLine PST.Dec(UP) PST.NewLine PST.Dec(AC1) PST.NewLine PST.Dec(AC2) PST.NewLine PST.Dec(AC3) PST.NewLine PST.Dec(AC4) PST.NewLine PST.Dec(AC5) PST.NewLine PST.Dec(AC6) PST.NewLine PST.Dec(B1) PST.NewLine PST.Dec(B2) PST.NewLine PST.Dec(MB) PST.NewLine PST.Dec(MC) PST.NewLine PST.Dec(MD) PST.NewLine PST.Dec(AC2) PST.NewLine waitcnt(clkfreq + cnt)
Which I have had similar luck with:
CON _clkmode = xtal1 + pll16x ' System clock → 80 MHz _xinfreq = 5_000_000 CR = 13 ' i2c bus contants _i2cNAK = 1 _i2cACK = 0 BMPSCL = 12 BMPSDA = 13 Baro_Addr = $EE 'i2c address of baro sensor { ' UT & UP Are Calculated by BMP Object. ' // Calculate True Temperature X1 := (UT - AC6) * AC5 / 2^15 X2 := MC * 2^11 / (X1 + MD) B5 := X1 + X2 T := (B5 + 8) / 2^4 T := Temp in 0.1 deg C ' // Calculate True Pressure B6 := B5 - 4000 X1 := (B2 * (B6 * B6 / 2^12)) / 2^11 X2 := AC2 * B6 / 2^11 X3 := X1 + X2 B3 := (((AC1 * 4 + X3) << oss) + 2) / 4 X1 := AC3 * B6 / 2^13 X2 := (B1 * (B6 * B6 / 2^12)) / 2^16 X3 := ((X1 + X2) + 2) / 2^2 B4 := AC4 * (X3 + 32768) / 2^15 B7 := (UP - B3) * (50000 >> oss) if B7 < $8000_0000 ' might need to be if B7 & $8000_0000 (B7 = -B7) else (B7 = +B7) p := (B7 * 2) / B4 else p := (B7 / B4) * 2 X1 := (p / 2^8) * (p / 2^8) X1 := (X1 * 3808) / 2^16 X2 := (-7357 * p) / 2^16 p := p + (X1 + X2 + 3791) / 2^4 'p = Pressure in Pa } VAR byte Baro_Data_f6 byte Baro_Data_f7 byte Baro_Data_f8 byte Baro_Data_f9 byte Baro_Data_fa byte Baro_Data_fb byte Baro_Data_fc byte Baro_Data_fd byte Baro_Data_fe byte Baro_Data_ff byte Baro_Data_AA byte Baro_Data_AB byte Baro_Data_AC byte Baro_Data_AD byte Baro_Data_AE byte Baro_Data_AF byte Baro_Data_B0 byte Baro_Data_B1 byte Baro_Data_B2 byte Baro_Data_B3 byte Baro_Data_B4 byte Baro_Data_B5 byte Baro_Data_B6 byte Baro_Data_B7 byte Baro_Data_B8 byte Baro_Data_B9 byte Baro_Data_BA byte Baro_Data_BB byte Baro_Data_BC byte Baro_Data_BD byte Baro_Data_BE byte Baro_Data_BF byte i2cSDA, i2cSCL word UP,UT,ac1,ac2,ac3,ac4,ac5,ac6, MB,MC,MD, B1, B2 long tTemp, tPressure, tAltitude, tAirSpeed OBJ 'umath : "umath" '0 Cog Debug : "FullDuplexSerialPlus" ' Use with Parallax Serial Terminal to Pub Start Debug.Start(31, 30, 0, 115200) ' // Baro.init: i2cSCL := BMPSCL i2cSDA := BMPSDA Init_i2c(i2cSDA, i2cSCL) repeat Debug.Str(String(13, "BMP-180 Demo")) ' // Read Pressure start_adcPres ' start the adc then readBaro ' read data via i2c bus UP := baro_f6 * 256 + baro_f7 ' raw 16 bit pressure data put in UP waitcnt(clkfreq/100 + cnt) ' // Read Temperature start_adcTemp ' start the adc then readBaro ' read data via i2c bus UT := baro_f6 * 256 + baro_f7 ' raw 16 bit pressure data in UT ' // Update Values AC1 := baro_AA * 256 + baro_AB AC2 := baro_AC * 256 + baro_AD AC3 := baro_AE * 256 + baro_AF AC4 := baro_B0 * 256 + baro_B1 AC5 := baro_B2 * 256 + baro_B3 AC6 := baro_B4 * 256 + baro_B5 B1 := baro_B6 * 256 + baro_B7 B2 := baro_B8 * 256 + baro_B9 MB := baro_BA * 256 + baro_BB MC := baro_BC * 256 + baro_BD MD := baro_BE * 256 + baro_BF ' // Calculate Ailtutude 'Convert(3, tTemp, tPressure) ' // Display Results Debug.Str(String(13, "Temperature = ")) Debug.Dec(tTemp) Debug.Str(String(13, "Pressure = ")) Debug.Dec(tPressure) Debug.Str(String(13, "Altitude = ")) Debug.Dec(tAltitude) Debug.Str(String(13, "Air Speed = ")) Debug.Dec(tAirSpeed) Debug.Str(String(13, "UP = ")) Debug.Dec(UP) Debug.Str(String(13, "UT = ")) Debug.Dec(UT) Debug.Str(String(13, "AC1 = ")) Debug.Dec(AC1) Debug.Str(String(13, "AC2 = ")) Debug.Dec(AC2) Debug.Str(String(13, "AC3 = ")) Debug.Dec(AC3) Debug.Str(String(13, "AC4 = ")) Debug.Dec(AC4) Debug.Str(String(13, "AC5 = ")) Debug.Dec(AC5) Debug.Str(String(13, "AC6 = ")) Debug.Dec(AC6) Debug.Str(String(13, "B1 = ")) Debug.Dec(B1) Debug.Str(String(13, "B2 = ")) Debug.Dec(B2) Debug.Str(String(13, "MB = ")) Debug.Dec(MB) Debug.Str(String(13, "MC = ")) Debug.Dec(MC) Debug.Str(String(13, "MD = ")) Debug.Dec(MD) 'waitcnt(clkfreq + cnt) ' // Return Calculated Altitude Pub Altitude ' Calculate Altitude return tAltitude ' // Return Calculated Temperature (Obtained via Convert) Pub Temperature return tTemp ' // Return Calculated Pressure (Obtained via Convert) Pub Pressure return tPressure Pub Baro_UT return UT Pub Baro_UP return UP Pub Baro_AC1 return AC1 Pub Baro_AC2 return AC2 Pub Baro_AC3 return AC3 Pub Baro_AC4 return AC4 Pub Baro_AC5 return AC5 Pub Baro_AC6 return AC6 Pub Baro_MB return MB Pub Baro_MC return MC Pub Baro_MD return MD Pub Baro_B1a return B1 Pub Baro_B2a return B2 ' // Convert to Calculated Values Pri Convert(mode, TempPtr, PressurePtr) | th, x1, x2, b5, b6, x3, b3, p, b4, b7 { ' // Calculate True Temperature X1 := (UT - AC6) * AC5 / 2^15 X2 := MC * 2^11 / (X1 + MD) B5 := X1 + X2 T := (B5 + 8) / 2^4 T := Temp in 0.1 deg C } X1 := ((UT - AC6) * AC5) ~> 15 'x2 := (mc << 11) / (x1 + md) X2 := (MC ~> 11) / (x1 + MD) B5 := X1 + X2 long[TempPtr] := (B5 + 8) ~> 4 { ' // Calculate True Pressure B6 := B5 - 4000 X1 := (B2 * (B6 * B6 / 2^12)) / 2^11 X2 := AC2 * B6 / 2^11 X3 := X1 + X2 B3 := (((AC1 * 4 + X3) << oss) + 2) / 4 X1 := AC3 * B6 / 2^13 X2 := (B1 * (B6 * B6 / 2^12)) / 2^16 X3 := ((X1 + X2) + 2) / 2^2 B4 := AC4 * (X3 + 32768) / 2^15 B7 := (UP - B3) * (50000 >> oss) if B7 < $8000_0000 ' might need to be if B7 & $8000_0000 (B7 = -B7) else (B7 = +B7) p := (B7 * 2) / B4 else p := (B7 / B4) * 2 X1 := (p / 2^8) * (p / 2^8) X1 := (X1 * 3808) / 2^16 X2 := (-7357 * p) / 2^16 p := p + (X1 + X2 + 3791) / 2^4 'p = Pressure in Pa } B6 := B5 - 4000 X1 := (B2 * ((B6 * B6) ~> 12)) ~> 11 'x2 := (AC2 * B6) ~> 11 X2 := AC2 * B6 ~> 11 X3 := X1 + X2 'B3 := ((((AC1 << 2) + X3) << mode) + 2) ~> 2 B3 := (((AC1 * 4 + X3) << mode) + 2) ~> 2 'X1 := (AC3 * B6) ~> 13 X1 := AC3 * B6 ~> 13 X2 := (B1 * ((B6 * B6) ~> 12)) ~> 16 X3 := ((X1 + X2) + 2) ~> 2 B4 := AC4 * (X3 + 32768) ~> 15 'B4 := (AC4 * (X3 + 32768)) >> 15 'unsigned 32 bit multiple 'B4 := umath.multdiv(AC4, (X3 + 32768), 32768) B7 := (UP - B3) * (50000 >> mode) 'unsigned 32 bit multiple 'if B7 < $8000_0000 if B7 & $8000_0000 'p := (B7 / B4) << 1 p := (B7 * 2) / B4 else 'p := (B7 * 2) / B4 p := (B7 * B4) * 2 'p := umath.multdiv((UP - B3), (100000 >> mode), B4) 'th := p ~> 8 'X1 := th * th X1 := (p ~> 8) * (p ~> 8) X1 := (X1 * 3038) ~> 16 X2 := (-7357 * p) ~> 16 long[PressurePtr] := p + (X1 + X2 + 3791) ~> 4 ' // EC_i2c_readbaro: Pri start_adcTemp i2cStart i2cWrite(Baro_Addr) 'write 0xEE to i2c bus i2cWrite($F4) 'write 0xF4 to i2c bus i2cWrite($EE) 'write 0xEE sequence to start temp conversion i2cStop Pri start_adcPres i2cStart i2cWrite(Baro_Addr) 'write 0xEE to i2c bus i2cWrite($F4) 'write 0xF4 to i2c bus i2cWrite($F4 ) 'write 0xF4 sequence to start pressure conversion i2cStop Pri readbaro i2cStart i2cWrite(Baro_Addr) 'write 0xEE to i2c bus sensor write address i2cWrite($F6) 'write 0xF6 to i2c bus sensor starting register i2cStart 'do a restart i2cWrite(Baro_Addr|1) 'write 0xEF (read cmd) to i2c bus sensor read address Baro_Data_f6 := (i2cRead(0)) 'i2c read 12 BYTES with ack bit Baro_Data_f7 := (i2cRead(0)) ' V Baro_Data_f8 := (i2cRead(0)) ' V Baro_Data_f9 := (i2cRead(0)) ' V Baro_Data_fa := (i2cRead(0)) ' V Baro_Data_fb := (i2cRead(0)) ' V Baro_Data_fc := (i2cRead(0)) ' V Baro_Data_fd := (i2cRead(0)) ' V Baro_Data_fe := (i2cRead(0)) ' V Baro_Data_ff := (i2cRead(1)) ' V i2cStop i2cStart i2cWrite(Baro_Addr) 'write 0xEE to i2c bus sensor write address i2cWrite($AA) 'write 0xF6 to i2c bus sensor starting register i2cStart 'do a restart i2cWrite(Baro_Addr|1) 'write 0xEF (read cmd) to i2c bus sensor read address Baro_Data_AA := (i2cRead(0)) 'i2c read 12 BYTES with ack bit Baro_Data_AB := (i2cRead(0)) ' V Baro_Data_AC := (i2cRead(0)) ' V Baro_Data_AD := (i2cRead(0)) ' V Baro_Data_AE := (i2cRead(0)) ' V Baro_Data_AF := (i2cRead(1)) ' V i2cStop i2cStart i2cWrite(Baro_Addr) 'write 0xEE to i2c bus sensor write address i2cWrite($B0) 'write 0xF6 to i2c bus sensor starting register i2cStart 'do a restart i2cWrite(Baro_Addr|1) 'write 0xEF (read cmd) to i2c bus sensor read address Baro_Data_B0 := (i2cRead(0)) 'i2c read 12 BYTES with ack bit Baro_Data_B1 := (i2cRead(0)) ' V Baro_Data_B2 := (i2cRead(0)) ' V Baro_Data_B3 := (i2cRead(0)) ' V Baro_Data_B4 := (i2cRead(0)) ' V Baro_Data_B5 := (i2cRead(0)) ' V Baro_Data_B6 := (i2cRead(0)) ' V Baro_Data_B7 := (i2cRead(0)) ' V Baro_Data_B8 := (i2cRead(0)) ' V Baro_Data_B9 := (i2cRead(1)) ' V i2cStop i2cStart i2cWrite(Baro_Addr) 'write 0xEE to i2c bus sensor write address i2cWrite($BA) 'write 0xF6 to i2c bus sensor starting register i2cStart 'do a restart i2cWrite(Baro_Addr|1) 'write 0xEF (read cmd) to i2c bus sensor read address Baro_Data_BA := (i2cRead(0)) 'i2c read 12 BYTES with ack bit Baro_Data_BB := (i2cRead(0)) ' V Baro_Data_BC := (i2cRead(0)) ' V Baro_Data_BD := (i2cRead(0)) ' V Baro_Data_BE := (i2cRead(0)) ' V Baro_Data_BF := (i2cRead(1)) ' V i2cStop PUB Baro_f6 return Baro_Data_f6 PUB Baro_f7 return Baro_Data_f7 PUB Baro_f8 return Baro_Data_f8 PUB Baro_f9 return Baro_Data_f9 PUB Baro_fa return Baro_Data_fa PUB Baro_fb return Baro_Data_fb PUB Baro_fc return Baro_Data_fc PUB Baro_fd return Baro_Data_fd PUB Baro_fe return Baro_Data_fe PUB Baro_ff return Baro_Data_ff PUB Baro_AA return Baro_Data_AA PUB Baro_AB return Baro_Data_AB PUB Baro_AC return Baro_Data_AC PUB Baro_AD return Baro_Data_AD PUB Baro_AE return Baro_Data_AE PUB Baro_AF return Baro_Data_AF PUB Baro_B0 return Baro_Data_B0 PUB Baro_B1 return Baro_Data_B1 PUB Baro_B2 return Baro_Data_B2 PUB Baro_B3 return Baro_Data_B3 PUB Baro_B4 return Baro_Data_B4 PUB Baro_B5 return Baro_Data_B5 PUB Baro_B6 return Baro_Data_B6 PUB Baro_B7 return Baro_Data_B7 PUB Baro_B8 return Baro_Data_B8 PUB Baro_B9 return Baro_Data_B9 PUB Baro_BA return Baro_Data_BA PUB Baro_BB return Baro_Data_BB PUB Baro_BC return Baro_Data_BC PUB Baro_BD return Baro_Data_BD PUB Baro_BE return Baro_Data_BE PUB Baro_BF return Baro_Data_BF ' // I2C Control Pri init_i2c(_i2cSDA, _i2cSCL) i2cSDA := _i2cSDA 'referances passed from main file for pin numbers i2cSCL := _i2cSCL outa[i2cSDA] := 0 'as inputs to start outa[i2cSCL] := 0 Pri readLocation(deviceAddress, deviceRegister) : i2cData | ackbit ' do a standard i2c address, then read ' read a device's register ackbit := _i2cACK i2cStart ackbit := (ackbit << 1) | i2cWrite(deviceAddress) ackbit := (ackbit << 1) | i2cWrite(deviceRegister) i2cStart ackbit := (ackbit << 1) | i2cWrite(deviceAddress | 1) ' repeat with read bit now set i2cData := i2cRead(_i2cNAK) i2cStop ' return the data return i2cData Pri writeLocation(deviceAddress, deviceRegister, i2cDataValue) : ackbit ' do a standard i2c address, then write ' return the ACK bit from the device address ackbit := _i2cACK i2cstart ackbit := (ackbit << 1) | i2cWrite(deviceAddress) ackbit := (ackbit << 1) | i2cWrite(deviceRegister) ackbit := (ackbit << 1) | i2cWrite(i2cDataValue) i2cStop return ackbit Pri i2cStop ' i2c stop sequence - the SDA goes LOW to HIGH while SCL is HIGH dira[i2cSCL] ~ dira[i2cSDA] ~ Pri i2cStart dira[i2cSDA] ~ dira[i2cSCL] ~ dira[i2cSDA] ~~ repeat until ina[i2cSCL] == 1 Pri i2cWrite(i2cData) : ackbit i2cData <<=24 ' init the clock line dira[i2cSCL] := 1 repeat 8 ' set the SDA while the SCL is LOW dira[i2cSDA] := (!(i2cData <-= 1) & 1) ' toggle SCL HIGH dira[i2cSCL] := 0 ' toogle SCL LOW dira[i2cSCL] := 1 ' setup for ACK - pin to input' dira[i2cSDA] := 0 ' read in the ACK dira[i2cSCL] := 0 ackbit := ina[i2cSDA] dira[i2cSCL] := 1 ' leave the SDA pin LOW dira[i2cSDA] := 1 return ackbit Pri i2cRead(ackbit): i2cData ' set the SCL to output and the SDA to input dira[i2cSDA] := 0 dira[i2cSCL] := 1 ' clock in the byte i2cData := 0 repeat 8 dira[i2cSCL] := 0 i2cData := (i2cData << 1) | ina[i2cSDA] dira[i2cSCL] := 1 ' send the ACK or NAK dira[i2cSDA] ~~ dira[i2cSCL] := 0 dira[i2cSDA] := !ackbit dira[i2cSCL] := 1 ' return the data return i2cData
However, of these 2 codes, I should get the same resulting values, but I dont, as you can see below.
Comments
If you give it the wrong BMP Address say $A5 instead of $EE the result you will see is -1. The numbers only show up when i use $EE, which was discovered by i2cscan.
Here is my code that kinda works:
in the same code I am testing my other sensor (mpu-9150) but with the mpu6050's driver (only way i can get it to work).
I have ran this with both of them plugged in, and just one with the same results for the bmp.
BMP i2c Test.zip