I2C Slave 20X2 and atomic access to word values

photomankc

New Member
Got a PICAXE 20X2 that is doing a great job running 3 sonar sensors for me and getting distance results for them. The PICAXE idea was to be a sub-controller to keep me from burning a core and 6 I/O lines in another processor polling and firing these sensors. The idea is to connect to the I2C bus and have the master read the values from the PICAXE when it needs or wants them.

It now comes to mind that since the I2C read is background to the rest of the program, and the values are all word size numbers, it will be very possible for the I2C read to get partially updated values as it reads through the memory locations and the PICAXE is bust scanning and updating away. I can't think of a reasonable way to either tell the picaxe to hold updates, or tell the master to wait.

Best idea I could come up with is an I2C command that tells the PICAXE to stop scanning, then the master reads the data, then start scanning again. That would slow things down a lot. Is there any way to make the PICAXE stretch the clock till it's all the data is updated? Are "put ADR, word DATA" considered atomic anyway?
 

hippy

Technical Support
Staff member
"PUT WORD" isn't atomic and this issue can can be a problem with any programmable I2C slave and it can be tricky coming up with a 'software handshaking solution'.

Telling the slave to start scanning, then waiting for data isn't always as much of a delay as it could be because the master is likely looping as well, so it can become wait for data, read data, initiate next scan, do things with that data, and, by the time the master comes to next check if data is available then it may already be ready for use. The processing becomes interleaved and overlapping rather than truly linear. Apart from the first time you don't necessarily have to check or wait for any data because, if the timing is right, you know it will be there for the taking.

It's like asking a secretary to get the next letter to be answered so they are getting that while you are answering the one you have. When you have completed that the next letter will be ready for you.
 

BCJKiwi

Senior Member
Another option is for the master to discard as invalid reading retrieved from the sub-controller that swings too wildly from the recent trend of readings.
How practical this suggestion is will depend on the typical rate that the distance readings change.

Alternatively some averaging/qualifying could be done as part of the sub-processor routines so the master only collects qualified results from the sub-processor.
 

photomankc

New Member
What I think I can do is to change the way that my enable/disable code works. Rather than check once before the entire sweep is done I could instead check at each sensor firing subroutine. That way the master can make it stop its sweep more quickly, read the data, and get out of the way faster. The problem with trying to time it is that these are cheap China knock-offs of the SRF05 boards. They have no timeout for a lost pulse and instead only the next trigger pulse will reset the echo line. As a result the time it takes to sweep is dependent on how big the bubble of space around the robot is. Also the loop timing on the brain-board is not going to be bang-on either.

OR....

Perhaps the best meathod instead will be to command a one-shot sweep, read the results, and repeat when needed rather than loop through continually. That way it's on demand, and the data is always good and I'm not constantly stopping the sweep in the middle.
 

flynnski

New Member
Dave

How about an external i2c EEprom that both MCs share. This would eliminate concurrent access to the data. Store the data in page mode, release the I2c bus and let the other master have the bus when the first master isn't using it.
 

photomankc

New Member
Just to finish out the thread... I came up with a solution that I think will work well enough. I added two locations in scratchpad ram for byte values. One value is used to signal that a ranging operation is underway if it is '0' then I know the values may be changing if it is '1' then I know we are in the quiet-down period between firing each sensor and the values are stable for about 50ms. Since it takes less than 2ms to read all 12 values that gives me plenty of time to 'wait for the green light' and then come grab the values between firing for a continuous scan. For a single-shot run I also added a scan-complete flag for the same purpose. Fire the scan, go off and do other stuff and check back to see if the flag is set. If so, then the results are ready so I can grab them and then trigger the next scan. Seems to work out nicely in testing so we will see how it goes in practice.
 
Top