PDA

View Full Version : I2C and eeprom woes



jboyles
05-14-2008, 10:44 AM
This is my first electronics project, and therefore first with the propeller. I will apologize in advance if the problem is painfully obvious.

I'm using the prop proto board in part as an I2C master to monitor 4 external LM92 temperature sensors and 1 PCF8591 ADC which is reading from a ASDX gage pressure sensor, 0-1 psi. The temperature sensors are running at 3.3V, and the ADC and pressure sensor are running at 5 V. To handle the voltage difference, I used the N-channel enhancement mosfets (IRF510) as bi-directional level shifters as described both in this forum and in the I2C specification. I'm using 4 trimpots (data and clock for 3.3V and 5V buses), all set to 4.7 k for pull-ups. I'm using P29 for SDA and P28 for SCL. To connect to the external sensors, I'm using cat-5e cable to rj-45 jacks, then cat-5e cable to the devices. I have the four striped wires tied to ground as the I2C spec recommends twisting each line with ground to avoid crosstalk. The striped wires are not connected at the devices to avoid ground loops. I do not have a capacitance meter, so I'm not sure what the bus capacitance is. The cables are roughly 1', 3', 3', 3', and 4'.

When I load a program into RAM, I use the Basic_I2C_Driver to scan the bus, and it finds 6 devices with the 5 expected addresses from my devices, and one with the address %1010_0000 which must be the eeprom. Funny thing is, if I try and load the program into the eeprom, I get an eeprom programming error. Additionally, if I try and reset the prop so that it is forced to load a program from eeprom, it does nothing. If I unplug my cat-5 cables from the rj-45 jacks, then the eeprom can be programmed and programs can be loaded from it. Of course, I can't talk to my devices anymore. Any ideas what may be going on?

While typing this it occurred to me that the 10k pull-up resistors for the eeprom may be too large given my bus capacitance. Would this make sense based on what I've seen? I'm guessing the easiest solution is to simply use pins other than P29 and P28 for my I2C bus.

Thanks for the help!

jboyles
05-14-2008, 10:55 AM
Spoke too soon about finding all the devices. I could've sworn I saw it find 6 devices, but when I use the devicePresent function, one of the devices is not there, and it is not showing up on the scan anymore (only 5 devices). Not surprisingly, it's the device on the 5 V side of the bus. I can swap around which of my 5 devices is on that side, and that's the one that's always missing. Has anyone used the mosfet approach, and is the IRF510 a suitable mosfet for this? If not, which specific mosfets would be good?

Mike Green
05-14-2008, 11:05 AM
First of all, the IRF510 MOSFET is not suitable for this sort of level shifter. It requires too high a gate voltage to conduct.

You don't need pullups on the 3.3V side of the I2C bus since the Protoboard already has them on both SCL and SDA.

Have you carefully checked the connections on the cables and to the various sensors?

If the Basic_I2C_Driver can find the various devices, but other Propeller code cannot, it may be a speed problem. Try shorter cables or lower pullup values on the 5V side.

Mike Green
05-14-2008, 11:10 AM
I've got a setup with just a 1K series resistor in the SCL and SDA leads from the Prop / EEPROM at 3.3V to 3 x PCA9554 I/O Expanders at different addresses running off 5V. It's only a few inches of wiring rather than several feet, but the 1K resistors work fine. There are 10K pullups on the 5V side.

jboyles
05-14-2008, 11:27 AM
Ok, I was worried about the IRF510s, but I'm not familiar with mosfets at all, and they were the only ones at the store that were even the right type. I don't think I need enough components to justify an order from digikey, so I'll try using the 1K series resistor instead of the mosfet approach.

I definitely won't be able to shorten the cables as the sensors need to be at fixed locations. All the connections seem to be fine, and like I said, the 3.3 V side of the bus is fine- I'm able to see them on the scan, with the devicePresent, and I'm able to read the temperatures correctly. I'm pretty sure the 5 V side is fine too as far as connections go, but I can't tell since the mosfets won't conduct.

Since I can't change the 10K pull ups present on the proto board and can't shorten my wires, wouldn't it be easiest to use different pins for SDA and SCL? I'm still not sure I get why the eeprom won't work with my devices all connected, yet the devices work (other than the 5 V side due to the mosfet issue). Would the additional (and unnecessary) pull ups I added on the 3.3 V side not affect the eeprom? Like I said, the eeprom works with the devices disconnected, which suggests to me that it's the change in bus capacitance that's responsible. The other possibility that comes to mind is an address collision, but that's not the case with my devices.

Thanks again!

Javalin
05-14-2008, 07:05 PM
Hello,

What code (is it public?) are you using for the LM92?

For 3.3v / 5v devices - most of the time you can just use a 1k in line resistor between the 5v and the 3.3v section, and a 4.7k pull-ups on the to lines or either 5v or 3.3v

James

Jonathan
05-14-2008, 09:12 PM
You might try Beau's i2c level shifter. I was dealing with an i2c ADC recently, and it was cranky with any other circuit I tried. It's very simple, an npn transistor and diode.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info (http://www.madlabs.info) - Home of the Hydrogen Fuel Cell Robot

jboyles
05-14-2008, 09:38 PM
Javalin said...
Hello,

What code (is it public?) are you using for the LM92?

For 3.3v / 5v devices - most of the time you can just use a 1k in line resistor between the 5v and the 3.3v section, and a 4.7k pull-ups on the to lines or either 5v or 3.3v

James


I'm using the Basic_I2C_Driver along with a bit of spin code I wrote:




PRI getTemp(addr) : temp | sign, byte1,byte2
'gets temp register from the LM92's, temp is 16 bit, 2's complement with LSB = 0.0625 C, bits 2-0 are status bits
'stores temp as integer temp x 10000

i2cbus.start(scl)
i2cbus.write(scl,addr) 'request read of LM92 temp
byte1 := i2cbus.read(scl,i2cbus#ACK) 'read first byte
byte2 := i2cbus.read(scl,i2cbus#ACK) 'read second byte
temp := byte1 << 8 'shift left to make room for next byte
temp |= byte2
sign := temp >> 15 'get sign bit
temp &= $7ff8 ' mask sign and status bits
temp >>= 3 'shift right to remove status bits
if sign == 0
temp *= 625
else 'shouldn't need have neg temps, but added for completeness
temp := -2_560_000 + 625 * (temp-1) 'temp is 2's complement
i2cbus.stop(scl)




I don't doubt that this could be optimized, but the LM92's can't be read any faster than once per second, and speed isn't an issue in my application. Also notice that I'm storing temp as an integer even though it's really measured to the ten thousandth.

I will try the 1K series resistor approach when I get a chance to work on it some more- sadly the only soldering iron I have at home is borrowed, and it's as big around as my finger.

jboyles
05-14-2008, 09:40 PM
Jonathan said...
You might try Beau's i2c level shifter. I was dealing with an i2c ADC recently, and it was cranky with any other circuit I tried. It's very simple, an npn transistor and diode.


I'll have to try that out. Do the npn and diode give you the same effect as the n-channel enhancement mosfet?

Javalin
05-14-2008, 09:42 PM
thanks jboyles. I've been trying on and off to get mine working - seems to be either 19 degrees or 392 degrees...!

James

Jonathan
05-14-2008, 10:23 PM
J,

I imagine the effect is roughly the same as mosfets, after all the objective is a level shifter.

What I do know is that with the above circuit, I got this ADC that wouldn't work right with any other circuit I tried to work just great on a protobaord using the dedicated i2c pins. With other circuits I got erratic results, for example the ADC reading a max count of 3000 or so. So other circuits did communicate with the chip, just not correctly. Looking at it all on a scope, I never really figured out why, but then I have limited equipment and comprehension. :)

Jonathan

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info (http://www.madlabs.info) - Home of the Hydrogen Fuel Cell Robot

jboyles
05-15-2008, 12:03 AM
Jonathan said...
J,

I imagine the effect is roughly the same as mosfets, after all the objective is a level shifter.

What I do know is that with the above circuit, I got this ADC that wouldn't work right with any other circuit I tried to work just great on a protobaord using the dedicated i2c pins. With other circuits I got erratic results, for example the ADC reading a max count of 3000 or so. So other circuits did communicate with the chip, just not correctly. Looking at it all on a scope, I never really figured out why, but then I have limited equipment and comprehension. :)

Jonathan


Jonathan,

One quick clarification- should the resistor from the transistor base to the 3.3 V be the same value as the pull up resistors? I'm using 4.7k pull ups, so should I have a 4.7k resistor from base to 3.3V?

Thanks,

Jeffrey

Jonathan
05-15-2008, 12:37 AM
I'm not qualified to say, I can only tell you what I did. I used the values as shown. The pullup on the far left is the one on the protoboard. So, all you need is the 3.3V 10K base pullup and the 5V pullup, plus of course the transistor and diode.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info (http://www.madlabs.info) - Home of the Hydrogen Fuel Cell Robot

jboyles
05-15-2008, 11:57 AM
Javalin said...
thanks jboyles. I've been trying on and off to get mine working - seems to be either 19 degrees or 392 degrees...!

James


Hi James-

Let me know how it goes. I had a few screw ups along the way with interpreting output, mostly not realizing that the status bits were coming through as well. I found the temperature register diagram on page 11 and the timing diagram at the top of page 13 of the datasheet particularly helpful. One thing I noticed that should be changed with my code is that, according to the datasheet, the master "typically" uses a NAK to signal to the LM92 that it has read the last byte. Not sure why this is the convention, and I can't tell any difference between using ACK (as in my posted code) and changing it to NAK for the second byte. Maybe typically means it doesn't really matter?

Jeffrey

Mike Green
05-15-2008, 12:45 PM
It does matter. The NAK tells the I2C slave device that it should not try to transmit another byte when the next clock pulse comes along. The stop sequence should reset the device, but some devices may require the NAK to properly reset the state machine.