Problems with master/slave communication

johndk

Senior Member
I'm pulling my hair out trying to track down a problem I've encountered using two 28x2 chips. I have one set up as a master and the other as slave. I have the master periodically check slave status by reading scratchpad location 0 and I have the master send commands to the slave by writing to location 1. So far so good. It worked great on my breadboard and "sometimes" works on my PCB board. When it works, it works well. However, on my PCB board, when it doesn't work, my master keeps reading either 255 or 0, neither of which values are at the slave location. I know the 255 is documented as an "error" condition. But I see no reference to 0.

The mystery is, why should it 'sometimes' work. I've checked that I have the proper pullups and even went so far as to replace them. I swapped out the 28x2 chips for new ones, which worked at first and then seemed to "degrade" to the same problem. I have a DS1307 RTC on the same i2c bus and both master and slave can talk to that just fine. I've checked and double checked that master and slave are both in the correct mode when communicating and that the scratchpad addresses are correct. I even had the master read the first 25 scratchpad locations, which all return the same nonsense 255 or 0 when the problem occurs.

I'm at wits end trying to track down this problem and would appreciate any suggestions anyone can think of. I'd share the circuit and code, but it's somewhat complex as I'm using 3 slots on the master and 2 slots on the slave all matched up to one controller board running 3 output boards. So maybe we can start with some general ideas to see if we can't home in on the problem. Just for information, I also have a 74150 multiplexer, a CD4060 counter, and a LM1117 voltage regulator on the PCB. And one final point. My master runs at the 8MHz default speed, but my slave idles at 8MHz, but "works" at 64MHz using an external 16MHz resonator. Slave speed seems to have no impact on reading the scratchpad, and neither do the i2vslow_8 or i2cfast_8 settings on the master (either one produces the same result .. good or bad).

I'm not expecting anyone to solve my problem, although that would be nice. I'm really looking for suggestions from those who have experience with master/slave communications as to what else I can look at.

John
 

inglewoodpete

Senior Member
First, don't use i2cFast: the code in a PIC configured as an i2c slave cannot keep up with a fast (sending at 400kHz) master.

Second, ensure that you have pull-up resistors wired correctly. Check the voltage on the scl and sda pins on both chips. Check with an LED and 330 resistor to 0v that the i2c signalling can be seen to flash the LED.

Thirdly, having two unsynchronised chips writing to the same scratchpad locations is an art. For the time being, use two bytes: one for master to slave and the other for slave to master. Each chip ONLY writes to one of the two bytes. Obviously, the master writes via i2c.

How long is the i2c bus? Standard i2c was designed to work on busses up to 1.2 metres maximum!

Debugging i2c is problematic. When you send serial data to your PC from either chip, internal i2c interrupts can be ignored due to the CPU firmware blocking them so that it can focus on the serial.

Finally, if you still need to, slow the i2c down further. If the master is running at 8MHz, use i2cSlow_16 in the hi2cSetup command. While it should not necessary, it can improve reliability by sending the data at half-speed (50kHz).
 

johndk

Senior Member
Thanks for the suggestions Pete. I actually checked/did all of those except the i2cslow_16. I was suspecting that it might have something to do with running the chips at different speeds. But in this case, that doesn't seem to be causing a problem as I AM keeping the scratchpad areas for master/slave messaging separated.

Here's the thing that has me really baffled. Out of desperation yesterday I changed one of the slave status constants from 3 to 30. Mind you, these are declared constants and therefore consistent throughout the code. Simply changing the "slave_ready" from 3 to 30 cleared everything up. No other changes to code, not even any other status constants. And no, there weren't any conflicts in any of the messaging constants. They're all declared in the same place and chronologically for just that reason. Go figure.

I'm glad it's behaving now and I probably shouldn't ask any further questions, just accept it. But I would surely like to know the reason for this.

John
 

PhilHornby

Senior Member
Picaxe busy doing something else?...

However, on my PCB board, when it doesn't work, my master keeps reading either 255 or 0, neither of which values are at the slave location. I know the 255 is documented as an "error" condition...
...
The mystery is, why should it 'sometimes' work.
I encountered similar issues with my very first Picaxe project. This involved a pair of 20x2's and a DS1307 on the I2C bus. All the I2C demo programs ran fine, but my program soon ran into the same problems as yours.

I came up with all sorts of convoluted schemes to try and overcome it - but the one that worked involved a couple of extra connections between Picaxes. Basically, I interrupted the target Picaxe and sent it off to execute a 'pause' statement. When it raised a data signal to say it was about to enter the pause, was when I found it 100% safe to remotely access the Scratchpad. I just assumed that certain commands rendered the Picaxe too busy to deal with remote Scratchpad access - though I never found any documentation to confirm that. The odd thing was, that the 'busiest' I could see the target Picaxe getting, was when it issued a 'pulsout Pin,30000' command...

With hind-sight, the architecture of my project was far from ideal - but you live and learn!
 

inglewoodpete

Senior Member
Basically, I interrupted the target Picaxe and sent it off to execute a 'pause' statement. When it raised a data signal to say it was about to enter the pause, was when I found it 100% safe to remotely access the Scratchpad. I just assumed that certain commands rendered the Picaxe too busy to deal with remote Scratchpad access - though I never found any documentation to confirm that. The odd thing was, that the 'busiest' I could see the target Picaxe getting, was when it issued a 'pulsout Pin,30000' command...
There are several 'blocking' commands, where the firmware enforces strict timing on itself, that must be avoided when using i2c. SerOut, SerTxd, SerIn, Debug, PulsIn, IRIn are among the ones that can interfere with i2c slave operation. i2c should not need the "interrupted" behaviour as you describe. "Paralysing" the chip to receive i2c is a sign of software design requiring additional attention.

Perhaps John could post his master and slave code, so that forum members can help sort out the real problem.
 

PhilHornby

Senior Member
I blame the hardware ;-)

"Paralysing" the chip to receive i2c is a sign of software design requiring additional attention.
"Paralysing" the chip, was the additional attention :confused:

Interestingly, you didn't list 'Pulsout' as a being a potential problem. I actually added a 'Pulsin' - which you do list - as part of the solution!
 

johndk

Senior Member
Interesting feedback! I was using a few brief sertxd statements on the slave side to indicate status for debugging. I hadn't turned them off. I could try that, just to see. But since all I did was to change my 'slave_ready' constant from 3 to 30, I can't see how that would make a difference. As I stated earlier, I'd be happy to share the code with interested members. But I hesitate to post it because it's long, somewhat involved, and in five parts. If some of you want a challenge and want a look, I can send it as a private message. However, unless it acts up again, this analysis would be only for the purpose of nailing down WHY it happens. This part of my code is doing what it should as of now.
 

inglewoodpete

Senior Member
I doubt that the issue will be purely because the constant changed from 3 to 30. I have found microcontrollers intercommunicating reliably with any protocol is not always a simple task.

And, you're right: I'm not about to volunteer to go through a large, unfamiliar program to find out why, either :). If your project now works, great but then observe it closely: the problem may re-occur when you least expect it.
 

johndk

Senior Member
Talk about quirky... Pete seems to be right. Although my code was working for a while, it must have been pure coincidence that I was hitting the slave at the right time. I fired it up this morning, and guess what ... same problem. So I disabled all the sertxd lines in the slave code. That seems to solve the problem. Hopefully, that will be the end of it. Thanks all!
 
Top