BMP085 i2c Problems...
zlantz
Posts: 136
I keep reading other peoples issues with the bmp085 and it seems the problem is, same one im having, that none of the i2c drivers just "work" as is. Everyone ends up needing a customized version of the bmp085 object or basic_i2c_driver. Read about something that works, go to try it, oops your file dont have "ALL" the code it is suppose to. ### Function dont exist. " I2C#OneAddr| " dont exist. Can we get a COMPLETE file Please?!?!?!
Cant find "Minimal_I2C_Driver" on OBEX (But referenced to by Basic_i2c_Driver.spin)
I have tried swapping out the sensor, i have 3 of them. Chances they ALL came Broken???
I have tried every combination i can think of with the BAROMETRO.spin, BMP085Object.spin & Basic_i2c_Driver.spin. I have even tried other i2c drivers.
i have a 10k on SCL & SDA to +3.3v.
ALL Data out is "0" or none at all.
With an O-scope i can see Data on SDA, but SCL is all mixed up kinda like a video signal with 3 states (AC) +3.3v(ON), 1.65v(Half ON), 0v(OFF) instead of two (DC) +3.3v(ON) or 0v(OFF).
Should i remove the SCL pull-up resistor to remove the possibility of the pin "Floating" at 1.65v?
To top it off this is the First time using i2c. I can access my prop eeprom as a "test", but no love on ANY other i2c sensors. I have some MLX90615's that are i2c and wont work as well (tried 7 of them; none work).
I would prefer not to scrap this project, as others have gotten the bmp085 to work. However, soon with the MPU-9050 being i2c as well if i cant get something working i might just have to.
I wrote my own SPI Protocol for my Magnetometer, it works well. Just cant get i2c to work. Or im being sent bunk parts from multiple dealers (x3).
Some Example Code (Not Working & Had to modify nearly everything to match my setup):
BAROMETRO.spin:
BMP085Object.spin:
Basic_i2c_Driver_E.spin:
Cant find "Minimal_I2C_Driver" on OBEX (But referenced to by Basic_i2c_Driver.spin)
I have tried swapping out the sensor, i have 3 of them. Chances they ALL came Broken???
I have tried every combination i can think of with the BAROMETRO.spin, BMP085Object.spin & Basic_i2c_Driver.spin. I have even tried other i2c drivers.
i have a 10k on SCL & SDA to +3.3v.
ALL Data out is "0" or none at all.
With an O-scope i can see Data on SDA, but SCL is all mixed up kinda like a video signal with 3 states (AC) +3.3v(ON), 1.65v(Half ON), 0v(OFF) instead of two (DC) +3.3v(ON) or 0v(OFF).
Should i remove the SCL pull-up resistor to remove the possibility of the pin "Floating" at 1.65v?
To top it off this is the First time using i2c. I can access my prop eeprom as a "test", but no love on ANY other i2c sensors. I have some MLX90615's that are i2c and wont work as well (tried 7 of them; none work).
I would prefer not to scrap this project, as others have gotten the bmp085 to work. However, soon with the MPU-9050 being i2c as well if i cant get something working i might just have to.
I wrote my own SPI Protocol for my Magnetometer, it works well. Just cant get i2c to work. Or im being sent bunk parts from multiple dealers (x3).
Some Example Code (Not Working & Had to modify nearly everything to match my setup):
BAROMETRO.spin:
CON _clkmode = xtal1 + pll16x ' System clock → 80 MHz _xinfreq = 5_000_000 CR = 13 BMPscl = 9 ' Currently on 8, 9 Bus BMPsda = 8 '#define BMP085_ADDRESS 0x77 // I2C address of BMP085 {{ The BMP085 module address is shown below. The LSB of the device address distinguishesbetween read (1) and write (0) operation, correspon ding to address 0xEF (read) and 0xEE (write). A7 A6 A5 A4 A3 A2 A1 W/R 1 1 1 0 1 1 1 0/1 }} 'BMPAddress = 11_0111 ' 0x77 = 110111 'BMPAddress = 10_1110 ' BMP - Write BMPAddress = 10_1111 ' BMP - Read ' P8 = SDA ' P9 = SCL VAR word t,p,t2,p2 OBJ Baro : "bmp085Object" Debug : "FullDuplexSerialPlus" PUB Init 'Debug.Start(31, 30, 0, 115200) waitcnt(clkfreq * 2 + cnt) 'Baro.init(BMPscl, BMPsda, 1) Baro.init(BMPscl, BMPsda, BMPAddress) repeat baro.GetPressureTemp(BMPscl,1,1,t,p) baro.GetPressureTemp(BMPscl, BMPAddress,1,t2,p2) debug.tx(0) ' Display Result Debug.Str(String(CR, "T = ")) Debug.Dec(t) Debug.Str(String(CR, "P = ")) Debug.Dec(P) baro.GetPressureTemp(BMPscl, BMPAddress,0,t2,p2) DEBUG.tx(13) ' Display Result Debug.Str(String(CR, "T = ")) Debug.Dec(t2) Debug.Str(String(CR, "P = ")) Debug.Dec(P2) waitcnt(clkfreq*1000 + cnt)
BMP085Object.spin:
{{ ┌──────────────────────────────────────────┐ │ BMP085 Driver 1.0 │ │ Author: Tim Moore │ │ Copyright (c) May 2010 Tim Moore │ │ See end of file for terms of use. │ └──────────────────────────────────────────┘ I2C addresses is 10_1110 breakout board availble (http://www.sparkfun.com/commerce/product_info.php?products_id=9694) Note: GetPressureTemp and GetPressureTempA are only usable from a single Cog. Calling from multiple Cogs will confuse the state machine }} Con _clkmode = xtal1 + pll16x ' System clock → 80 MHz _xinfreq = 5_000_000 'BMPscl = 9 ' Currently on 8, 9 Bus 'BMPsda = 8 OBJ i2cObject : "basic_i2c_driver_E" '0 Cog umath : "umath" '0 Cog ser : "FullDuplexSerialPlus" VAR long ac1, ac2, ac3, ac4, ac5, ac6, b1, b2, mb, mc, md 'see the datasheet for what these mean long state, time, temput long delays[4] DAT shifts long 50000, 50000>>1, 50000>>2, 50000>>3 PUB Init(i2cSCL, i2cSDA, _deviceAddress) ''initializes BMP085 ''reads in sensor coefficients etc. from eeprom i2cObject.Initialize(i2cSCL, i2cSDA) state := 0 delays[0] := clkfreq/222 '4.5ms delays[1] := clkfreq/133 '7.5ms delays[2] := clkfreq/74 '13.5ms delays[3] := clkfreq/39 '25.5ms result := true 'read all the coefficient and sensor values from eeprom ac1 := i2cObject.readLocation16(i2cSCL, _deviceAddress, $AA) ac2 := i2cObject.readLocation16(i2cSCL, _deviceAddress, $AC) ac3 := i2cObject.readLocation16(i2cSCL, _deviceAddress, $AE) ac4 := i2cObject.readLocation16(i2cSCL, _deviceAddress, $B0) ac5 := i2cObject.readLocation16(i2cSCL, _deviceAddress, $B2) ac6 := i2cObject.readLocation16(i2cSCL, _deviceAddress, $B4) b1 := i2cObject.readLocation16(i2cSCL, _deviceAddress, $B6) b2 := i2cObject.readLocation16(i2cSCL, _deviceAddress, $B8) mb := i2cObject.readLocation16(i2cSCL, _deviceAddress, $BA) mc := i2cObject.readLocation16(i2cSCL, _deviceAddress, $BC) md := i2cObject.readLocation16(i2cSCL, _deviceAddress, $BE) if ac1 == 0 OR ac2 == 0 OR ac3 == 0 OR ac4 == 0 OR ac5 == 0 OR ac6 == 0 OR b1 == 0 OR b2 == 0 OR mb == 0 OR mc == 0 OR md == 0 result := false elseif ac1 == $ffff OR ac2 == $ffff OR ac3 == $ffff OR ac4 == $ffff OR ac5 == $ffff OR ac6 == $ffff OR b1 == $ffff OR { } b2 == $ffff OR mb == $ffff OR mc == $ffff OR md == $ffff result := false ~~ac1 'sign extend correctly, note ac4, ac5, ac6 are not sign extended ~~ac2 ~~ac3 ~~b1 ~~b2 ~~mb ~~mc ~~md PUB GetPressureTemp(i2cSCL, _deviceAddress, mode, TempPtr, PressurePtr) ' Temp in 0.1°C ' Pressure in Pa ' repeat until result == true if (result := GetPressureTempA(i2cSCL, _deviceAddress, mode, TempPtr, PressurePtr)) == false waitcnt(delays[mode&3] + cnt) '4.5ms/7.5/13.5/25.5 PUB GetPressureTempA(i2cSCL, _deviceAddress, mode, TempPtr, PressurePtr) | up ' mode is oversampling setting ' 0 - 1 sample every 4.5ms ' 1 - 2 samples every 7.5ms ' 2 - 4 samples every 13.5ms ' 3 - 8 samples every 25.5ms ' Temp in 0.1°C ' Pressure in Pa ' mode &= 3 'make sure 0-3 case state 0: i2cObject.WriteLocation(i2cSCL, _deviceAddress, $f4, $2e) 'request for temp time := cnt state++ 1: if (cnt-time) > delays[0] '4.5ms temput := i2cObject.readLocation16(i2cSCL, _deviceAddress, $F6) i2cObject.WriteLocation(i2cSCL, _deviceAddress, $f4, $34|(mode<<6)) 'request for pressure time := cnt state++ 2: if (cnt-time) > delays[mode] '4.5ms/7.5/13.5/25.5 up := i2cObject.readLocation24(i2cSCL, _deviceAddress, $F6) up >>= (8 - mode) state := 0 Convert(temput, up, mode, TempPtr, PressurePtr) result := true PRI Convert(ut, up, mode, TempPtr, PressurePtr) | x1, x2, b5, b6, x3, b3, p, b4, th '' x1 := ((ut - ac6) * ac5) ~> 15 x2 := (mc << 11) / (x1 + md) b5 := x1 + x2 long[TempPtr] := (b5 + 8) ~> 4 b6 := b5 - 4000 x1 := (b2 * ((b6 * b6) ~> 12)) ~> 11 x2 := (ac2 * b6) ~> 11 x3 := x1 + x2 b3 := ((((ac1 << 2) + x3) << mode) + 2) ~> 2 x1 := (ac3 * b6) ~> 13 x2 := (b1 * ((b6 * b6) ~> 12)) ~> 16 x3 := ((x1 + x2) + 2) ~> 2 '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 & $80000000 ' p := (b7 / b4) << 1 'else ' p := (b7 * 2) / b4 p := umath.multdiv((up - b3), (100000 >> mode), b4) th := p ~> 8 x1 := th * th x1 := (x1 * 3038) ~> 16 x2 := (-7357 * p) ~> 16 long[PressurePtr] := p + ((x1 + x2 + 3791) ~> 4) {{ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ TERMS OF USE: MIT License │ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ │is furnished to do so, subject to the following conditions: │ │ │ │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ │ │ │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ }}
Basic_i2c_Driver_E.spin:
'' Basic I2C Routines Version 1.1 '' Written by Michael Green and copyright (?) 2007 '' '' Modified by James Burrows '' '' Modified Tim Moore Jul/Aug 08 '' Slow down to handle 100Khz devices '' Add readlocation16, writeValue, readValue16 '' Added slave clock stretching to read/write '' Changed call to start when reading register to restart - different order of SDA/SCL for taking them high '' '' Permission is given to use this in any program for the Parallax '' Propeller processor as long as this copyright notice is included. '' This is a minimal version of an I2C driver in SPIN. It assumes '' that the SDA pin is one higher than the SCL pin. It assumes that '' neither the SDA nor the SCL pins have pullups, so drives both. '' These routines are primarily intended for reading and writing EEPROMs. '' The low level I2C are provided for use with other devices, but the '' read/write byte routines assume a standard I2C serial EEPROM with a '' 16 bit device address register, paged writes, and acknowledge polling. '' All of these read/write routines accept an EEPROM address up to 19 '' bits (512K) even though the EEPROM addressing scheme normally allows '' for only 16 bits of addressing. The upper 3 bits are used as part of '' the device select code and these routines will take the upper 3 bits '' of the address and "or" it with the supplied device select code bits '' 3-1 which are used to select a particular EEPROM on an I2C bus. There '' are two schemes for selecting 64K "banks" in 128Kx8 EEPROMs. Atmel's '' 24LC1024 EEPROMs allow simple linear addressing up to 256Kx8 ($00000 '' to $3FFFF). Microchip's 24LC1025 allows for up to 512Kx8, but in two '' areas: $00000 to $3FFFF and $40000 to $7FFFF. Each EEPROM provides '' a 64K "bank" in each area. See the device datasheets for details. '' This will work with the boot EEPROM and does not require a pull-up '' resistor on the SCL line (but does on the SDA line ... about 4.7K to '' +3.3V). According to the Philips I2C specification, both pull-ups '' are required. Many devices will tolerate the absence of a pull-up '' on SCL. Some may tolerate the absence of a pull-up on SDA as well. '' Initialize may have to be called once at the beginning of your '' program. Sometimes an I2C device is left in an invalid state. This '' will reset the device to a known state so it will respond to the I2C '' start transition (sent out by the i2cStart routine). '' To read from or write to an EEPROM on pins 28/29 like the boot EEPROM: '' CON '' eepromAddress = $7000 '' VAR '' byte buffer[32] '' OBJ '' i2c : "Minimal_I2C_Driver" '' PRI readIt '' if i2c.ReadPage(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer, 32) '' abort ' an error occurred during the read '' PRI writeIt | startTime '' if i2c.WritePage(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer, 32) '' abort ' an error occured during the write '' startTime := cnt ' prepare to check for a timeout '' repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, eepromAddress) '' if cnt - startTime > clkfreq / 10 '' abort ' waited more than a 1/10 second for the write to finish '' Note that the read and write use something called paged reads/writes. '' This means that any read using ReadPage must fit entirely in one '' EEPROM if you have several attached to one set of pins. For writes, '' any write using i2cWritePage must fit entirely within a page of the '' EEPROM. Usually these pages are either 32, 64, 128 or 256 bytes in '' size depending on the manufacturer and device type. 32 bytes is a '' good limit for the number of bytes to be written at a time if you '' don't know the specific page size (and the write must fit completely '' within a multiple of the page size). The WriteWait waits for the '' write operation to complete. Alternatively, you could wait for 5ms '' since currently produced EEPROMs will finish within that time. CON ACK = 0 ' I2C Acknowledge NAK = 1 ' I2C No Acknowledge Xmit = 0 ' I2C Direction Transmit Recv = 1 ' I2C Direction Receive BootPin = 28 ' I2C Boot EEPROM SCL Pin EEPROM = $A0 ' I2C EEPROM Device Address I2CDelay = 100_000 'delay to lower speed to 100KHz I2CDelayS = 10_000 'clock stretch delay Var long SDA PUB Initialize(SCL, mSDA) ' An I2C device may be left in an SDA := mSDA ' invalid state and may need to be outa[SCL] := 1 ' reinitialized. Drive SCL high. dira[SCL] := 1 dira[SDA] := 0 ' Set SDA as input repeat 9 outa[SCL] := 0 ' Put out up to 9 clock pulses outa[SCL] := 1 repeat 9 outa[SCL] := 0 ' Put out up to 9 clock pulses outa[SCL] := 1 if ina[SDA] ' Repeat if SDA not driven high quit ' by the EEPROM dira[SCL]~ ' Now let them float dira[SDA]~ ' If pullups present, they'll stay HIGH PUB Start(SCL) '| SDA ' SDA goes HIGH to LOW with SCL HIGH 'SDA := SCL + 1 outa[SCL]~~ ' Initially drive SCL HIGH dira[SCL]~~ outa[SDA]~~ ' Initially drive SDA HIGH dira[SDA]~~ 'waitcnt(clkfreq / I2CDelay + cnt) outa[SDA]~ ' Now drive SDA LOW 'waitcnt(clkfreq / I2CDelay + cnt) outa[SCL]~ ' Leave SCL LOW PUB ReStart(SCL) '| SDA ' SDA goes HIGH to LOW with SCL HIGH 'SDA := SCL + 1 outa[SDA]~~ ' Initially drive SDA HIGH dira[SDA]~~ outa[SCL]~~ ' Initially drive SCL HIGH 'waitcnt(clkfreq / I2CDelay + cnt) outa[SDA]~ ' Now drive SDA LOW 'waitcnt(clkfreq / I2CDelay + cnt) outa[SCL]~ ' Leave SCL LOW PUB Stop(SCL) '| SDA ' SDA goes LOW to HIGH with SCL High 'SDA := SCL + 1 outa[SCL]~~ ' Drive SCL HIGH outa[SDA]~~ ' then SDA HIGH dira[SCL]~ ' Now let them float 'waitcnt(clkfreq / I2CDelay + cnt) dira[SDA]~ ' If pullups present, they'll stay HIGH PUB WriteNS(SCL, data) : ackbit '| SDA '' Write i2c data. Data byte is output MSB first, SDA data line is valid '' only while the SCL line is HIGH. Data is always 8 bits (+ ACK/NAK). '' SDA is assumed LOW and SCL and SDA are both left in the LOW state. '' Doesn't do clock stretching so would work without pull-up on SCL 'SDA := SCL + 1 ackbit := 0 data <<= 24 repeat 8 ' Output data to SDA outa[SDA] := (data <-= 1) & 1 outa[SCL]~~ ' Toggle SCL from LOW to HIGH to LOW outa[SCL]~ dira[SDA]~ ' Set SDA to input for ACK/NAK outa[SCL]~~ ackbit := ina[SDA] ' Sample SDA when SCL is HIGH outa[SCL]~ dira[SCL]~~ outa[SDA]~ ' Leave SDA driven LOW dira[SDA]~~ PUB ReadNS(SCL, ackbit): data | b', SDA '' Read in i2c data, Data byte is output MSB first, SDA data line is '' valid only while the SCL line is HIGH. SCL and SDA left in LOW state. '' Doesn't do clock stretching so would work without pull-up on SCL 'SDA := SCL + 1 data := 0 dira[SDA]~ ' Make SDA an input repeat 8 ' Receive data from SDA outa[SCL]~~ ' Sample SDA when SCL is HIGH b := ina[SDA] outa[SCL]~ data := (data << 1) | b outa[SDA] := ackbit ' Output ACK/NAK to SDA dira[SDA]~~ dira[SCL]~ ' Toggle SCL from LOW to HIGH to LOW dira[SCL]~~ outa[SDA]~ ' Leave SDA driven LOW PUB Write(SCL, data) : ackbit | wait', SDA '' Write i2c data. Data byte is output MSB first, SDA data line is valid '' only while the SCL line is HIGH. Data is always 8 bits (+ ACK/NAK). '' SDA is assumed LOW and SCL and SDA are both left in the LOW state. '' Requires pull-up on SCL ' 'SDA := SCL + 1 ackbit := 0 data <<= 24 repeat 8 ' Output data to SDA outa[SDA] := (data <-= 1) & 1 'waitcnt(500 + cnt) dira[SCL]~ ' Toggle SCL from LOW to HIGH to LOW 'waitcnt(500 + cnt) 'wait := cnt 'repeat while 0 == ina[SCL] ' if (cnt-wait) > clkfreq/I2CDelayS ' quit dira[SCL]~~ 'waitcnt(500 + cnt) dira[SDA]~ ' Set SDA to input for ACK/NAK 'waitcnt(500 + cnt) dira[SCL]~ 'waitcnt(500 + cnt) wait := cnt repeat while 0 == ina[SCL] if (cnt-wait) > clkfreq/I2CDelayS quit ackbit := ina[SDA] ' Sample SDA when SCL is HIGH dira[SCL]~~ 'waitcnt(500 + cnt) outa[SDA]~ ' Leave SDA driven LOW 'waitcnt(500 + cnt) dira[SDA]~~ PUB Read(SCL, ackbit):data | wait', SDA '' Read in i2c data, Data byte is output MSB first, SDA data line is '' valid only while the SCL line is HIGH. SCL and SDA left in LOW state. '' Requires pull-up on SCL ' 'SDA := SCL + 1 data := 0 dira[SDA]~ ' Make SDA an input repeat 8 ' Receive data from SDA 'waitcnt(500 + cnt) dira[SCL]~ ' Sample SDA when SCL is HIGH 'waitcnt(500 + cnt) wait := cnt repeat while 0 == ina[SCL] if (cnt-wait) > clkfreq/I2CDelayS quit data := (data << 1) | ina[SDA] 'waitcnt(500 + cnt) dira[SCL]~~ 'waitcnt(500 + cnt) outa[SDA] := ackbit ' Output ACK/NAK to SDA 'waitcnt(500 + cnt) dira[SDA]~~ 'waitcnt(500 + cnt) dira[SCL]~ ' Toggle SCL from LOW to HIGH to LOW 'waitcnt(500 + cnt) wait := cnt repeat while 0 == ina[SCL] if (cnt-wait) > clkfreq/I2CDelayS quit dira[SCL]~~ 'waitcnt(500 + cnt) outa[SDA]~ ' Leave SDA driven LOW PUB ReadChar(SCL): data | ackbit', SDA '' Read in i2c data, Data byte is output MSB first, SDA data line is '' valid only while the SCL line is HIGH. SCL and SDA left in LOW state. 'SDA := SCL + 1 data := 0 dira[SDA]~ ' Make SDA an input repeat 8 ' Receive data from SDA waitcnt(clkfreq / I2CDelay + cnt) outa[SCL]~~ ' Sample SDA when SCL is HIGH waitcnt(clkfreq / I2CDelay + cnt) data := (data << 1) | ina[SDA] outa[SCL]~ if data == 0 ackbit := NAK else ackbit := ACK outa[SDA] := ackbit ' Output ACK/NAK to SDA dira[SDA]~~ outa[SCL]~~ ' Toggle SCL from LOW to HIGH to LOW waitcnt(clkfreq / I2CDelay + cnt) outa[SCL]~ outa[SDA]~ ' Leave SDA driven LOW PUB ReadPage(SCL, devSel, addrReg, dataPtr, count) : ackbit '' Read in a block of i2c data. Device select code is devSel. Device starting '' address is addrReg. Data address is at dataPtr. Number of bytes is count. '' The device select code is modified using the upper 3 bits of the 19 bit addrReg. '' Return zero if no errors or the acknowledge bits if an error occurred. devSel |= addrReg >> 15 & 10 Start(SCL) ' Select the device & send address ackbit := Write(SCL, devSel | Xmit) ackbit := (ackbit << 1) | Write(SCL, addrReg >> 8 & $FF) ackbit := (ackbit << 1) | Write(SCL, addrReg & $FF) reStart(SCL) ' Reselect the device for reading ackbit := (ackbit << 1) | Write(SCL, devSel | Recv) repeat count - 1 byte[dataPtr++] := Read(SCL, ACK) byte[dataPtr++] := Read(SCL, NAK) Stop(SCL) return ackbit PUB ReadByte(SCL, devSel, addrReg) : data '' Read in a single byte of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. if ReadPage(SCL, devSel, addrReg, @data, 1) return -1 PUB ReadWord(SCL, devSel, addrReg) : data '' Read in a single word of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. if ReadPage(SCL, devSel, addrReg, @data, 2) return -1 PUB ReadLong(SCL, devSel, addrReg) : data '' Read in a single long of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. '' Note that you can't distinguish between a return value of -1 and true error. if ReadPage(SCL, devSel, addrReg, @data, 4) return -1 PUB WritePage(SCL, devSel, addrReg, dataPtr, count) : ackbit '' Write out a block of i2c data. Device select code is devSel. Device starting '' address is addrReg. Data address is at dataPtr. Number of bytes is count. '' The device select code is modified using the upper 3 bits of the 19 bit addrReg. '' Most devices have a page size of at least 32 bytes, some as large as 256 bytes. '' Return zero if no errors or the acknowledge bits if an error occurred. If '' more than 31 bytes are transmitted, the sign bit is "sticky" and is the '' logical "or" of the acknowledge bits of any bytes past the 31st. devSel |= addrReg >> 15 & 10 Start(SCL) ' Select the device & send address ackbit := Write(SCL, devSel | Xmit) ackbit := (ackbit << 1) | Write(SCL, addrReg >> 8 & $FF) ackbit := (ackbit << 1) | Write(SCL, addrReg & $FF) repeat count ' Now send the data ackbit := ackbit << 1 | ackbit & $80000000 ' "Sticky" sign bit ackbit |= Write(SCL, byte[dataPtr++]) Stop(SCL) return ackbit PUB WriteByte(SCL, devSel, addrReg, data) '' Write out a single byte of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. if WritePage(SCL, devSel, addrReg, @data, 1) return true ' james edit - wait for 5ms for page write to complete (80_000 * 5 = 400_000) waitcnt(400_000 + cnt) return false PUB WriteWord(SCL, devSel, addrReg, data) '' Write out a single word of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. '' Note that the word value may not span an EEPROM page boundary. if WritePage(SCL, devSel, addrReg, @data, 2) return true ' james edit - wait for 5ms for page write to complete (80_000 * 5 = 400_000) waitcnt(400_000 + cnt) return false PUB WriteLong(SCL, devSel, addrReg, data) '' Write out a single long of i2c data. Device select code is devSel. Device '' starting address is addrReg. The device select code is modified using the '' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. '' Note that the long word value may not span an EEPROM page boundary. if WritePage(SCL, devSel, addrReg, @data, 4) return true ' james edit - wait for 5ms for page write to complete (80_000 * 5 = 400_000) waitcnt(400_000 + cnt) return false PUB WriteWait(SCL, devSel, addrReg) : ackbit '' Wait for a previous write to complete. Device select code is devSel. Device '' starting address is addrReg. The device will not respond if it is busy. '' The device select code is modified using the upper 3 bits of the 18 bit addrReg. '' This returns zero if no error occurred or one if the device didn't respond. devSel |= addrReg >> 15 & 10 Start(SCL) ackbit := Write(SCL, devSel | Xmit) Stop(SCL) return ackbit ' *************** JAMES'S Extra BITS ********************* PUB devicePresent(SCL,deviceAddress) : ackbit ' send the deviceAddress and listen for the ACK Start(SCL) ackbit := Write(SCL,deviceAddress | 0) Stop(SCL) if ackbit == ACK return true else return false PUB writeLocation(SCL,device_address, register, value) start(SCL) write(SCL,device_address) write(SCL,register) write(SCL,value) stop (SCL) PUB readLocation(SCL,device_address, register) : value start(SCL) write(SCL,device_address | 0) write(SCL,register) restart(SCL) 'note change to restart from start, SCP1000 doesnt work without this change and so far works with other devices write(SCL,device_address | 1) value := read(SCL,NAK) stop(SCL) return value PUB readLocation16(SCL,device_address, register) : value start(SCL) write(SCL,device_address | 0) write(SCL,register) restart(SCL) write(SCL,device_address | 1) value := read(SCL,ACK) value <<= 8 value |= (read(SCL,NAK) & $ff) stop(SCL) return value PUB readLocation24(SCL,device_address, register) : value start(SCL) write(SCL,device_address | 0) write(SCL,register) restart(SCL) write(SCL,device_address | 1) value := read(SCL,ACK) value <<= 8 value |= (read(SCL,ACK) & $ff) value <<= 8 value |= (read(SCL,NAK) & $ff) stop(SCL) return value PUB writeValue(SCL,device_address, value) start(SCL) write(SCL,device_address) result := write(SCL,value) stop (SCL) PUB readValue16(SCL,device_address) : value start(SCL) write(SCL,device_address | 1) value := read(SCL,ACK) value <<= 8 value |= (read(SCL,NAK) & $ff) stop(SCL) return value PUB readValue8(SCL,device_address) : value start(SCL) write(SCL,device_address | 1) value := read(SCL,NAK) stop(SCL) return value
Comments
The only thing that I can think of that could cause that would be if the BMP058 uses clock-stretching - though it's not mentioned in the datasheet. I notice that the basic I2C driver you're using drives the lines both high and low, if the BMP is holding the clock low (stretching it) while the driver is trying to assert a high, that could be causing that problem.
The forum has some screwyness with the percent sign. Please verify that you're using percent 111_0111 as the the device address.
I've cobbled together a quick routine using my Spin-based driver that's worked with everything I've tested in on.
BMP058 - Archive.zip
Chris- i tried that code, bmp not found when i run on 28 & 29, but when i try 8 & 9 prop term stays blank.
Does the prop ONLY do i2c on pins 28 & 29 ????
i am seriously considering trying to find a i2c to serial ic to use so that all i have purchased (i2c) is not junk. or it is time to quit using the propeller all together.
This is a serious stress as my project uses 3+ i2c sensors, and right now, i cant use a single one of them.
Ive had a few hurdles so far that were a bit rough to get over & the forums here had the answers. Hopefully this one too will become a past problem.
i also keep noticing that different people have gotten it to work with different addresses...
BAROMETRO.spin uses address "1"
http://mbed.org/users/tkreyche/notebook/bmp085-pressure-sensor/ uses 0xEF
the DATASHEET uses 1110_1110 Write & 1110_1111 Read
your example $77 = 0x77 = 0111_0111
which one is correct? is there a default ("1") that works for Everything?
i changed your code around a bit, more for a debug setting.
In response to the addressing question in post #5, I2C devices have a 7-bit identifier, followed by a read/write bit. The basic I2C driver expects the user to format the 7-bit ID and 1-bit read/write into a single byte. I wrote my driver to accept just the 7-bit ID and automatically add the read/write depending on what method was called, so $77 should work for all methods -- I2C.write($77,$00,$01)) write the value $01 to register $00 of device $77, I2C.read($77,$00) return the value in register $00 of device $77, should be just that simple.
is 10k ohm too much for 3.3v? i know the datasheet said 10k was the max, and my eeprom uses a 10k so ive got plenty layin around. I wouldnt expect it to be too much. i know when i was trying to get my 7 mlx90615's to work (all i2c) i tried various values with no luck.
changed from the spin i2c driver to the pasm driver and it acts totally different, still no correct data out. if the pins are right or wrong, it gives the same output forwards and backwards (sda = 8 & scl = 9 or sda = 9 & scl = 8) even on pins that have NOTHING hooked up to them i still get the same output.
I don't see any pull up resistors on I2C traces.
You need think I2C are open collector that need's that
they are on there, follow the two i2c traces, they go to the only two resistors on that side of the board & theyr hooked to 3.3v (R5 & R6)
So i have tried running FreqSynth out on pins 8 & 9.... here we have a problem. i didnt expect one pin on my prop chip to be jacked up...
Still same problems, no data, etc, etc.
could i have over heated it during soldering??? i did it on a pretty low temp and only heated it very little. i have one left i can hook up via silver epoxy.
also, sinci i dont have any, as far as i know working, i2c devices, i am considering connecting two propeller chips together using the i2c bus.
when i scoped the square waves, no, it was unplugged. that was right out of my prop pin. i have since switched to my smd pcb that was in my helicopter. checked its square wave and it was clean. still the same problems with i2c.
right now, if my i2c is unplugged and i run BAROMETRO, sda has some pulses, scl is high, same for read REGISTERS. but i2cScan has a clock signal on scl & data on sda, Nothing is plugged in the i2c header, that is what the prop is producing from the code. as shown in photos below. when plugged in... read REGISTERS both lines are pulled low ~0.027v, BAROMETRO has most data like output & i2cScan is closest to BAROMETRO.
*** i2cScan CAN find propeller EEPROM but finds 0 devices for bmp085.
i just got my mpu-6050 module in the mail today so ive got a second i2c device to test with that i didnt have to soldier.
going to try your i2c master/slave demo right quick before i mess with the mpu-6050.
i2cScan.spin:
OScope i2c BMP085:
BAROMETRO SCL:
BAROMETRO SDA:
i2cScan SCL:
i2cScan SDA:
OScope Readings i2c UnPlugged:
BAROMETRO SDA Line (SCL was High 3.3v):
read REGISTERS SDA line (SCL was High):
i2cScan SCL:
i2cScan SDA:
I am starting to think my bmp085's are toasting when i am soldering them up.
got one left, gonna try silver conductive epoxy & a homemade breakout board. if that fails, its off to an MPL115A1 SPI pressure sensor (or get a bmp085 breakout).
so i can only conclude that the bmp085's are themselves damaged, or are being damaged when soldered.
MPU-6050.spin:
INSTANT GRATIFICATION!!!!
Works 100%. Demo code works 100%. And it is running on i2c.
I am glad I spent the $30 to try this little guy out. When it comes to producing my own circuit I will just get the $8 MS5607. But still $8 vs $2 it is more expensive than the BMP180, the extra few bucks makes it worth it. In retrospect, the module should only be $15 or $20 at the most.
BMP085 demo - Archive.zip