Another Bus Length Question: P82B715 I2C extender

jsmanson

Member
Looking for some help on using 40 meters of Cat5 twisted pair with I2c (slow), with 3 nodes. I have both the P82B715 extenders, as well as the alternate P82B96 units as well. What will be hooked up I2C wise:

Node1: 40x2, clock, eeprom, lcd, P82B715 (total capacitance = 50pf)
10 meters away, node 2: 20x2, P82B715 (total capacitance 20pf)
30 meters away from node 2, node3: 40x2, digital POT, P82B715 (total capacitance 30pf)

cable capacitance would be about 2,000 pf at 50pf/lin meter at 100khz.

I have nodes 1 and 3 communicatiing now using the 715's, but I am getting some I2C transmission errors (data values of 255) that I would like to deal with.

I am using 4.7K pullups on the pic side at each of the two ends, I think I have two 270 ohms pullups on the bus side at the moment to get things 'going', but I want to select the proper resisters to fit my situation.

I have been using this document from nxp, which discusses in detail both chip options: http://www.nxp.com/documents/data_sheet/P82B715.pdf

It looks like 4.7k pullups on each of the three node's (pic side, one on each line), and 3 - 750 ohm pullups on the bus side (which result in a net bus pullup resistance of 250 ohms) should meet the I2c Bus and maximum current draw specification on the 715's.

So two questions for anyone familiar with this stuff:

1. Am I OK with the resistance values as stated (I am effectively building the circuuit diagram shown in figure 6 of the pdf)?

and

2. Would I be better off using the P82B96, and driving the bus side at say 12 volts?

Thanks in advance!!

John
 

inglewoodpete

Senior Member
From my experience, the P82B715 works fairly reliably up to about 14 metres at 100kbits/sec. You can see why if you have an oscilloscope - the line capacitance starts to kill off the rise time of the pulses until they don't rise far enough in the time available (10uS) to register on the receiving device (master or slave). The smaller the pull-up resistors are (in ohms), the better the performance since the capacitance (reactance) becomes less significant. However, the current sinking capability of the senders (master or slave end P82B715) limits the minimum resistance that can be used. 12 volt operation is not likely to work any better, since the RC time constant of the transmission line does not change.

The only real option you have, if you want to persist with i2c (with P82B715s, of course) is to slow down the data rate to 50kHz or 25kHz. This doubles (or quadruples) the length of the pulses, reducing the effect of the line capacitance. As an example, if you are running your 40X2 at 8MHz, use i2cSlow_16 or i2cSlow_32, which will result in a data rate of 50kbits/s or 25kbits/s.

Beyond that, you will need to go to a balanced medium, like RS485. That brings with it the need for extra code to do the OSI Layer 2 stuff (eg address recognition etc)
 

hippy

Technical Support
Staff member
If the problem is with 40X2 to 40X2 I2C communications; one thing to check is your "I2C transmission errors (data values of 255)" are actual transmission errors and not some issue of software timing.
 

jsmanson

Member
Thanks very much for the suggestions guys, I tried slowing the bus down to 50kb/sec using i2c_slow_16 on an 8mhz clock speed, the the enclosed file shows the extent of bad reads, about 90% bad or worse (I just add "88" to the data stored in the remote scratchpad "LOC", and store that at the next address.). Data does eventually get through, as you can see from the screen shot of the results. The 40 meters of cat5 is buried underground, and it was raining yesterday, that may have introduced some nasties into the line as well. I do have some 485 transmitter ic's in my pile of stuff, but I don't have much program space let to write a bunch of additional code, so I'd like to perservere with I2C a bit longer if I can. I'll try 25kb/sec as well. The datasheet says the setup should be good to 40-50 meters in total length, I am within that. I will stick the i2c data on a scope and send that as well, so you can see how it looks.....

Hippy, not sure what could be wrong programming wise, this is the i2c related tatements I am using:

hi2csetup I2CMASTER, i2c_timer,i2cslow_8, i2cbyte; go back to byte transfers (eprom uses word transfers so I have to flip back and forth)
.....
main program ......

get_data:

'part 1 - read in the data
inputs = inputs_old
'hi2cout [i2c_lcd],(254,88) 'clear screen
'hi2cout [i2c_lcd],(254,71,1,1) 'col 1, row ?
'hi2cout [i2c_lcd],("New Data...") '

temp = 28
'hi2cout [i2c_lcd],(10,13,"adc_dom:") '
call get_data_byte
if temp1 <> 255 then
inputs = temp1
end if

temp = 3
'hi2cout [i2c_lcd],(10,13,"f_well:") '
call get_data_word
if tempw_low <> 255 then
f_toilet = tempw
end if

etc etc

..........
example subroutine.....

get_data_byte:
pause 30
tempw2 = 0
temp3 = 0
temp4 = 0
try:
hi2cin [i2c_remote],temp, (temp1,temp2)
temp3 = temp1 + trans_byte
sertxd("BYTE, loc=",#temp,", val=",#temp1,",v+b=",#temp3,",and remote byte=",#temp2,":",cr,lf)
pause 2000
if temp3 <> temp2 then
inc temp4
if temp4 < 8 then
pause 40
hi2cout [i2c_remote],100,(0)
pause 30
goto try:
else
temp1 = 255
end if
end if
return
 

Attachments

hippy

Technical Support
Staff member
Hippy, not sure what could be wrong programming wise
Nor me, but what happens if one PICAXE tries to read or write I2C and the slave side is busy doing something else so cannot respond in a timely manner ?

How do you avoid that situation or otherwise deal with it ? How do you know it is data corruption rather than the slave PICAXE having not responded ?
 

jsmanson

Member
Right. I see your point. The remote is running at 64mhz if that helps, the main 40x2 is running at 8. The remote cycles around a few times a second, but I could stick a 2 second pause in there so it's not writing the scratchpad so often. Will the picaxe service a remote i2c read or write request during a pause command Hippy? If so, that should significantly reduce the possibility of read/write/i2c conflicts.....
 

jsmanson

Member
Rethink time, pauses won't work because I will miss the incoming flow pulses during a pause, I could add a 20M2 to just count pulses (lbenson's original idea last year lol), and flag the remote 40x2 when each liter of water has accumlated (=330 pulses), that will happen no more often than once every 2 secs at full flow x 5 flow sensors, that should work fine. It's maybe a bit resource (pin) intensive, but I could wire up 5 digital 'ins' on the 40x2 that go high when each of the 5 flow channels get to "1 liter", and the 40x2 could reply on one of another 5 output pins to advise the data is received, and to reset the output pin low. The 40x2 can then manage i2c communications (through a pause commend), update the display at it's comparitive 'leisure'.... I could use interrupts, but I'm not sure I need to in this situation.

So Hippy and others, your comments on this apporach would be appreciated:

40x2 Tasks,

main:
64mhz:
increment loop counter;
check each of 5 flow input lines from separate 20M2 "Flow" picaxe (see code below);
if one is high, alknowlege using appropriate flow output line, and increment one of 5 flow variables;
check if house Picaxe is wanting to run a commnd by reading scratchpad memory location "0", run appropriate command (digital output) if true;
pause 100; 'enables i2c comms during main loop
if loop counter > 25 (say) then call update:
goto main:

update: (runs once every every 2-4 seconds)
set loopcounter back to 0;
Put flow variables into scratchpad memory for the house 40x2 to read using I2c;
16mhz:
update display
64 mhz:
return

20M2 tasks:
32Mhz:
main:
check each of 5 inputs for a high condiition (flow pulse), if so increment one of 5 pulse flow variables;
if pulse variable > 330, then set flow back to zero, and set respective flow output pin high;
check each of 5 'flow reset' pins for high condition, if so, drop the respective flow output back to low;
goto main:
 

lbenson

Senior Member
You could do it with just 4 pins--3 output from the 20M2 to say which one of 5 (or up to 7) had counted a liter, one input to say the output had been read and could be set back to 0. 40x2 doesn't return its acknowledgement to 0 until it reads 0 on the 3 counter pins.

Or two pins: 20M2 output goes high to say it has counted up to a liter on one of its inputs; 40x2 output goes high to say I'm going to count now for a small fraction of a second; 20M2 pulses 1 to 5 times; 40X2 pin goes low to say "I got it".
 

jsmanson

Member
Thanks Larry, very elegant, I like to two pin option - don't do much pulse work so if you can help that would be great.... I could set the 20m2 output as an rising interrupt on the 40x2, and do the 'read' in a 40x2 interrupt routine I presume... in that routine, the "pulsin" command would be called, and would measure the length of a pulse starting at logic 0 over a set period, then set the output high to start the pulse, when the reading period is done, make sure the count is > 0, if so, then set return output back to low and return to the main program loop, otherwise repeat the read process. Meanwhile on the 20m2 (at 32mhz) , when the input goes high, send a pulseout in the form, say pulsout "x.x,y", where "Y" is, say, 4 times the number of the data to be sent (dec 1-5), max length would be 5 x 4 x 1.25us = 12.5us, the 40x2 on the pulsin has a resolution of 0.625us, so that should work for decifering the data at the other end allowing for timing shifting etc. I am trying to get this interrupt process to run as quickly as possible so I don't miss any flow pulses, and to minimise I2c processing issues possibly running concurrently. That sound good?
 

lbenson

Senior Member
I said pulses, but it would probably be easier for the 40X2 to read with "COUNT pin, period, wordvariable".

I don't recall how your programs are structured, but it could all be done pretty asynchronously if you wanted to avoid interrupts.

20M2 is cycling at high speed, counting pulses from the water meters; when a count exceeds 330, it asserts the signal and continues looping and counting, but testing with every loop to see if the 40X2 "ready" pin is asserted. Then it pulls the signal low, waits a millisecond or so, and then performs the desired number of HIGH, LOW cycles, each taking a fraction of a millisecond.

"low countPin : pause 1 : do while meterNo > 0 : high countPin : low countPin : dec meterNo : loop"

The 40X2 in its looping checks the signal line, and when convenient, asserts its "ready" pin, waits for the signal line to go low, and executes the count statement. It times out, and you have your count. You probably need to test a bit to figure out the timing of the count statement--long enough for 5 high/low transitions at the speed at which the 20M2 is running, plus a little.

No problem with using interrupts if that works for you.
 
Last edited:

jsmanson

Member
Right, I think I was being a bit too concerend about time length of the transaction, even if it's 10-20ms, that would probably only be a pulse or two of flow missed, less than 1%.

The I2C communication between the remotes has completely stopped the last day or two, so I will be taking a step or two back to track that down. the local I2C (between the main 40x2 and the eeprom and the clock) is working flawlessly, no data errors, only issues for transactions through the bus extender. Still not sure if the I2C issue is the 'long' wire issue, or if there is a programming issue between the picaxes. The day before I was getting about 70% of the I2C requests through the extender without errors, so I was considering just living with that as it's really just a monitoring station at the house anyways, but now it looks like I will have to find a more robust solution anyways.

I am still thinkning about switching from the P82B715 extender to the P82B96 extender for the reasons outlined in the partial datasheet enclosed. Looks like the waveform is much improved with the '96.
 

Attachments

jsmanson

Member
For those that may be interested, this is the scope of the I2C comms between the 2 40x2's, about 40-50 meters apart running CAT5, Using the p82b715, 4.7k pullups on each 'end', with 300 ohm pullups (one on each line) on the bus. 2 twisted pair, one pair carrying a ground, one pair 5 volts along with the respective signal lines.

The PDF is 2 pages, second page is a blow up of the first.

Pretty ugly signal, but the full transaction is occuring most times. I am getting about 30% 'failures' , a failure being a value of 255. I am getting some occasional bad values (all data is read twice from different registers and compared), but mostly 255 erorrs, not data mismatches.

I have ordered a few PCA9600 extenders from these guys: http://sandboxelectronics.com/?p=1098.

Hoping they will eliminate these errors!
 

jsmanson

Member
For those that may be interested, this is the scope of the I2C comms between the 2 40x2's, about 40-50 meters apart running CAT5, Using the p82b715, 4.7k pullups on each 'end', with 300 ohm pullups (one on each line) on the bus. 2 twisted pair, one pair carrying a ground, one pair 5 volts along with the respective signal lines.

The PDF is 2 pages, second page is a blow up of the first.

Pretty ugly signal, but the full transaction is occuring most times. I am getting about 30% 'failures' , a failure being a value of 255. I am getting some occasional bad values (all data is read twice from different registers and compared), but mostly 255 erorrs, not data mismatches.

I have ordered a few PCA9600 extenders from these guys: http://sandboxelectronics.com/?p=1098.

Hoping they will eliminate these errors!

---woops - this time here is the file!!
 

Attachments

lbenson

Senior Member
The pdf you posted earlier shows 470 ohm resistors on both ends of the Lx, Ly cables between the end P82B715s. Don't know if that would make a difference.
 

jsmanson

Member
I just put the resistors at one end of the line so the equivilent of 2-470's is around 235 ohms. I think the 9600 extender chips will work better in any event, they completely isolate each end, which the 715 does not do, the latter configuration requires each I2C device to 'pull down' the entire network of devices (less the '10x assistance' that the 715 provides, where the 9600 separates the signal at each node, if I understand this stuff correctly. I have also had better luck just putting in longer delays (pause 100 at 8mhz) between I2C commands as well, program runs a bit slower but that doesn't really matter... Thanks Larry and others for sticking with me on this project, many many hours lol!
 

rossko57

Senior Member
I just put the resistors at one end of the line ...
There are good reasons to have terminating resistors at each end, rather than at one end or in the middle. (They will be acting as transmission line terminators as well as pullups)
I've no doubt that in 99 cases you'd get away with it fine. But as you're experiencing failures, it may not pay to scrimp.
 
Top