What is I2C slave behavior when master does an Hi2CIN?

wapo54001

Senior Member
I'm trying to get reliable I2C between a master 20X2 and a slave 28X2, and haven't succeeded. I've found another thread in the forum where someone has the same problem -- cannot communicate reliably while his slave is busy reading sensors.

I would like to create an I2C solution that least affects the slave 28X2 operation and I feel that I don't know enough about the automatic operation of Picaxe slaves and masters to make intelligent changes to my program.

The I2C Tutorial document has little to say about differences between Picaxe-to-Picaxe and Picaxe to peripheral I2C. I cannot find anything about how the slave reacts when the master tries to read the scratchpad or how prepare the slave to insure that the read is successful.

If reliable I2C imposes limitations on the running program in order to work reliably, I think more information is needed about how the Picaxes communicate and what is required of the running programs to support that communication. Since my slave program needs to keep moving with minimum interruption, I would like to do what is needed, but no more.

Is there a document that I've overlooked that will give me those answers?
 
Last edited:

Technical

Technical Support
Staff member
All the i2c work in slave mode is in the background, based on internal hardware interrupts which are generated when the i2c silicon detects an i2c message from the master.
Interrupts are only disabled during critical time sensitive operations, which mainly occurs with serin/out/txd/debug type commands. So it is best to avoid those in the i2c slave in your particular situation (or to workround).
 

BeanieBots

Moderator
I've just had a similar issue with I2C slave device reading sensors, putting the value in scratchpad and then being read by a master 28X2.
My project uses DS18B20 sensors, displays on a local LCD and also sends over Bluetooth using hserout, so I was expecting a few conflicts.
The solution was to add a request line.
The master sets the request line high and waits for a "pause 70" at 8Mhz.
The slave responds to an interrupt on this line and just sits in the interrupt routine until the line goes low again.
It took a while to discover that the pause needed to be so long but I guess this is required to allow the slave to finish it's serout lines.
 

wapo54001

Senior Member
From the experiences of BeanieBots and the other thread that I found on the issue and my own experience, it appears to me that some additional guidance on the use of I2C in the real world would be very useful. Folks are taking the assurances of the manual that it's all 'automatic' and works without intervention but really it does not in all cases.

I sure would like some clarification on the timing of the background interrupt in the slave versus how long the master will wait for a reply, etc, and whatever other information is needed to make the process transparent and efficiently manageable in software.

FWIW I stuck a PAUSE 1000 (at 32MHz) in the main program and my I2C improved dramatically, but I still don't know if that's an optimal solution or how much of a pause is needed. In doing this, it definitely affects the quality of the main program which is minutely controlling four devices at high speed, and I'd rather not use a PAUSE.

It seems to me that HI2CIN needs to generate an interrupt in the slave for the slave's main program to react to just as HI2COUT does so that code can be written to accommodate the I2C command. Without that interrupt it becomes necessary to build in a repeating PAUSE that is only useful when an I2C command is being processed which means each cycle is affected even if the I2C command happens only infrequently. I would think that it should not be necessary to have to add a third wire to a two-wire communication system as BeanieBots had to do in order to make his I2C work.

I don't know if this is available, but I really would like more information about how I2C works specific to the Picaxe chips and also more realistic advice on how to manage I2C in an environment where the slave is very busy. Right now it's too much "art" and not enough "science."
 

AllyCat

Senior Member
Hi,

I think the clue is in Technical's comment in #2:

Interrupts are only disabled during critical time sensitive operations, which mainly occurs with serin/out/txd/debug type commands. So it is best to avoid those in the i2c slave in your particular situation (or to workround).
Basically, you need to avoid all "blocking" commands in your program. In addition to SERIN (and similar), that may include SEROUT, PULSIN, COUNT and PULSOUT, in addition to IRIN, RFIN, etc.. I've found a similar need with M2s, to keep the time variable incrementing reasonably accurately.

Sometimes workarounds are possible; for example fast polling loops to replace PULSIN/OUT and COUNT and sending (only) single bytes to HSEROUT, in place of SEROUT. Sometimes alternative methods are possible using PEEK/POKESFR, but ultimately one reaches the stage where the workarounds (to use PICaxe) are more trouble than they're worth. Then you have to make a decision whether to use (for example) multiple processors, additional hardware assistance, a compiled langauge or even assembler, etc..

As for the I2C interrupts (or any others), the requirements should be reasonably obvious from the base PIC data sheet, or some of the Microchip Application Notes. Generally, the "silicon" (chip hardware) will support only single-byte buffers and thus an (unmasked) interrupt is likely to be required before any subsequent byte is sent or received.

Cheers, Alan.
 

Buzby

Senior Member
...It took a while to discover that the pause needed to be so long but I guess this is required to allow the slave to finish it's serout lines.
I had a similar problem when I was experimenting with servicing very fast interrupts, over 700 per second. It all boils down to remembering that a PICAXE only checks for interrupts between instructions. A command like hserout 0, ( "My long string of text. ") takes as long as the UART takes to squirt the string out, so at lower baud rates it takes correspondingly longer before the whole command finishes, even though hserout is not classed as a blocking command.

I never use the known blocking commands ( sertxd, serout, readtemp, etc. ) unless I'm absolutely certain that I can tolerate an interrupt response which is delayed, ( or worse, missed !. ).
 

wapo54001

Senior Member
I have read the manual, I have NO blocking commands in my program.

It appears that I2C is not reliable when the slave is busy even with no blocking commands in use. If this is true -- and BeanieBots experience matches mine and at least one other person's experience showing that it is true -- then that should to be described somewhere with parameters that allow a programmer to intelligently deal with it.

The interrupt I am suggesting is an interrupt that works with the running program so that it can pause its activity long enough for the I2C request to complete. I don't know if this is a good answer, it's the one that comes to mind to deal with the HI2CIN request at the slave.

As for the I2C interrupts (or any others), the requirements should be reasonably obvious from the base PIC data sheet, or some of the Microchip Application Notes. Generally, the "silicon" (chip hardware) will support only single-byte buffers and thus an (unmasked) interrupt is likely to be required before any subsequent byte is sent or received.
The answers may be there. But it sounds to me like Rev Ed have done their own coding here and that information will not be in any Microchip datasheet.

Also, I don't think I'm in any sort of minority when I describe myself as not interested nor technically adept enough nor have the time for finding, reading, and then understanding detailed multi-hundred page Microchip data sheets or application notes which are mostly over my head. I'm one of the main group of users who need to have the chips work in the way they are described in the manual, and when there are considerations to deal with, to be advised of those considerations and the workarounds.

But I get it -- there isn't time to do everything that needs doing, and I'm moving on.
 

Technical

Technical Support
Staff member
I had a similar problem when I was experimenting with servicing very fast interrupts, over 700 per second. It all boils down to remembering that a PICAXE only checks for interrupts between instructions.
Do not confuse hardware silicon interrupts with software 'interrupt'. They are very different things and silicon interrupts occur immediately, not between each command. Which is exactly why they they need to be temporarily disabled during, for instance, a serout byte being sent - or else the timing of that byte would become corrupt (as the silicon interrupt takes time to process) and the serout would fail.
 

Technical

Technical Support
Staff member
It appears that I2C is not reliable when the slave is busy even with no blocking commands in use. If this is true -- and BeanieBots experience matches mine and at least one other person's experience showing that it is true -- then that should to be described somewhere with parameters that allow a programmer to intelligently deal with it.
No - i2c silicon interrupts takes priority over most commands and so is very reliable for the slave. The only time it is temporarily disabled is when it is strictly necessary to prevent another time-critical command becoming corrupt. A single core micro can quite simply not be doing two things at exactly the same time - servicing a i2c slave read in the background and also simultaneously processing a timing critical BASIC command in the foreground.

BB states he was using serial commands for the LCD and 1-wire commands as well, both time critical as already explained. Hence the need for a simple handshake in his project.
 

AllyCat

Senior Member
Hi,

I have read the manual, I have NO blocking commands in my program.
I wasn't aware that there is a definitive (complete) list of blocking commands in the/a manual (or anywhere else?). But (now) it appears that there are two types of command that can "prevent the flow" [to avoid using the word "interrupt" in a different sense] of the processing: i.e. the acknowledged "Blocking" commands and those that are "critical time-sensitive operations". The former generally referring to the affect on foreground (user program) tasks and the latter to the background (system/silicon) tasks.

What we really need is two definitive "lists" that identify what "design decisions" have been taken for the PICaxe firmware. Some are obvious (and acknowledged) such as SEROUT, IRIN, etc., but what about HSEROUT, PULSIN, PULSOUT, COUNT and "time" etc.? As Technical says, the PIC(axe) can't do two things at the same time, so do "silicon" interrupts occur at the expense of accurate PULSIN/OUT, etc., or vice versa?

However, I suppose we really also need a third "list" that identifies which interrupts ("silicon" and "polled") might be "lost", or are only delayed (i.e. they have a pending flag). Some of that can be inferred from the base PIC datasheet, but not all.

Cheers, Alan.
 

wapo54001

Senior Member
Do not confuse hardware silicon interrupts with software 'interrupt'. They are very different things and silicon interrupts occur immediately, not between each command. Which is exactly why they they need to be temporarily disabled during, for instance, a serout byte being sent - or else the timing of that byte would become corrupt (as the silicon interrupt takes time to process) and the serout would fail.
Technical, can you then shed any light on why I2C isn't reliable when the slave is very busy? If the I2C interrupt (in silicon) is immediate and takes precedence, why doesn't it stop the slave program and read write the scratchpad reliably when the slave is busy?
 

Technical

Technical Support
Staff member
Please provide an example program where you are having the issue. It is reliable in our experience.
 

Technical

Technical Support
Staff member
As Technical says, the PIC(axe) can't do two things at the same time, so do "silicon" interrupts occur at the expense of accurate PULSIN/OUT, etc., or vice versa?
Silicon interrupts (e.g. i2c byte received) set an internal silicon flag and then, if currently active, immediately fire the internal silicon interrupt, which is then processed immediately, hence interrupting the foreground BASIC code immediately.

Timing critical BASIC commands temporarily disable the silicon interrupt until they have completed to prevent corruption. So the i2c byte received flag is still instantly set, but in this case is processed only when the timing critical section of the BASIC command is complete (note this is not the whole BASIC command is complete, just the timing sensitive part of it). Hence the processing of the i2c command is delayed a while, but should still work most of the time.
 

bpowell

Senior Member
Would it be possible to enable clock stretching with a well placed poke? This might help resolve i2c timing issues.
 

AllyCat

Senior Member
Hi,

Thanks Technical. But are PULSIN and HSEROUT("A long string"), for example, considered as "Timing-critical commands"? It appears that they are "blocking". So, might a 600 ms pulse for "PULSIN", arriving after a 600 ms delay, cause a "pending" interrupt to need to wait for more than a second (@4 MHz)?

Cheers, Alan.
 

AllyCat

Senior Member
Hi,

How would the program code know that a 600 ms delay/pulse were starting and not a 10 us delay/pulse?

Cheers, Alan.
 

bpowell

Senior Member
I thought you saying there were two separate commands...a "Pause 600" and then a "Pulsein"...interrupts would be checked in-between those two commands. (at the completion of the pause, and before the pulsein)
 

AllyCat

Senior Member
Hi,

No, I was proposing that a program might contain a PULSIN, but then there could be a delay of up to 655 ms (i.e. less than the timeout period) before the leading edge of the pulse arrived. Then a further 600 ms (also less than the timeout) before the trailing edge terminated the pulse.

Since the program code doesn't know what to "expect" during all this time, I believe it has to be running in a tight (10 us) polling loop. Or maybe the design decision was that PULSE.. accuracy (or even detection) should be sacrificed at the expense of supporting silicon interrupts?

Cheers, Alan.
 

BeanieBots

Moderator
Just to clarify. My project required a handshake line because my slave uses one-wire and serial commands.
If I remove those commands (it is still very busy using ReadADC10 commands) it is absolutely spot-on with PICAXE to PICAXE I2C data transfers.
 

wapo54001

Senior Member
In researching I2C I think I've learned that the pullup resistor value depends on a variety of factors such as length of connection, capacitance, etc, and there is no single correct value. I've also read somewhere that if there is only one master and one slave on the circuit that often no pullup is required at all. My I2C circuit is short, no more than three inches and well clear of power lines. My one deviation from the Picaxe manual is that I'm using 4K99 1% instead of 4K7 resistors. Is that enough deviation from the specification to cause erratic I2C? I would think not, but, ?
 

bpowell

Senior Member
I've never heard of NOT needing pull-up resistors...I've tried (by accident) to have 1 Master and 1 Slave talk w/out pull-ups and it failed miserably. I've built circuits with a variety of I2C components, and I always use 4k7 pull-up...never had a problem. I'd imagine 4.9 will be okay as well.

If you're trying to troubleshoot an I2C problem, nothing beats a logic-analyzer or a scope...probe the lines and see what you see.

Sometimes I will have status LEDs flick on and off while the chip is running a key task...that way I can visualize how long something is taking...or I can see, "Yeah, I2C is happening at the exact same time as Serial Out..."
 

inglewoodpete

Senior Member
With only a 3" i2c bus, you should have no problems with pullups between 3k and 10k.

My current project uses 2 x 28X2 chips (master/slave) connected with a 500mm i2c bus between the two. Each chip uses 2 x 10k pullups (Ie at each end of each i2c wire) and works reliably. The PICAXEs use PWM to drive a directly-connected 50volt/500W RGB lighting controller using switching FETs, which is bound to be a very noisy electrical environment.

From the little you have told us about your program, I have to assume you are using blocking commands (commands that turn off all interrupts for their duration). Like ReadTemp, PulsIn and most Serial commands. Possibly the ReadADC command??
 
Last edited:

wapo54001

Senior Member
If you're trying to troubleshoot an I2C problem, nothing beats a logic-analyzer or a scope...probe the lines and see what you see.

Sometimes I will have status LEDs flick on and off while the chip is running a key task...that way I can visualize how long something is taking...or I can see, "Yeah, I2C is happening at the exact same time as Serial Out..."
I was wondering about putting a scope on it -- which led me to wonder if the very inexpensive analog/digital scope offered somewhere in the forums here would be a good candidate for a task like that.

Another thing I wondered -- could a check of the status of the data line by the slave's running program be used to trigger some reaction in the main program at appropriate times or is it too constant to identify requests from the master?
 

Technical

Technical Support
Staff member
No, don't do this. Let's see your problematic code, we can't help any more without it.
 

wapo54001

Senior Member
From the little you have told us about your program, I have to assume you are using blocking commands (commands that turn off all interrupts for their duration). Like ReadTemp, PulsIn and most Serial commands. Possibly the ReadADC command??
ReadADC is blocking? I did not know that. If it is, it explains my problem -- it is used frequently in my program. I don't remember seeing that in any discussion of blocking commands.
 

Technical

Technical Support
Staff member
readadc is NOT a command that disables silicon interrupts, as it is not timing critical.
See post 20 in this thread.

The term 'blocking' is not the same as disabling silicon interrupts to prevent timing issues within a command.
Blocking means the program gets 'stuck' on that BASIC line - as is the case of irin or serin with no timeout. That is not the same as what is under discussion here.
 

Buzby

Senior Member
... readadc is NOT a command that disables silicon interrupts, as it is not timing critical...
I have a program using readadc, and it did seem to interfere with interrupts, so I re-arranged the code so readadc was only performed when interrupts were not required.

In the light of technical's post I will investigate my code a bit closer, maybe something else was messing the interrupts.
 

bpowell

Senior Member
Buzby,

Perhaps readADC blocks software interrupts (those that are polled by the PICAXE software in-between lines of code) but does NOT block silicone interrupts (those that trigger and over-ride the PICAXE execution flow to be serviced)?
 

wapo54001

Senior Member
Silicon interrupts (e.g. i2c byte received) set an internal silicon flag and then, if currently active, immediately fire the internal silicon interrupt, which is then processed immediately, hence interrupting the foreground BASIC code immediately.

Timing critical BASIC commands temporarily disable the silicon interrupt until they have completed to prevent corruption. So the i2c byte received flag is still instantly set, but in this case is processed only when the timing critical section of the BASIC command is complete (note this is not the whole BASIC command is complete, just the timing sensitive part of it). Hence the processing of the i2c command is delayed a while, but should still work most of the time.
Well, my face is red and I'm embarrassed, but at the same time I'm very glad we had this discussion. I found my problem -- the very code that I was using to verify that the code was working -- watching results with SERTXD -- was the code that kept HI2CIN from working properly. I blocked that code and everything worked.

Technical, thank you for sticking with us on this hunt, I would not have solved my issues without the help of this thread.
 

inglewoodpete

Senior Member
-- the very code that I was using to verify that the code was working -- watching results with SERTXD -- was the code that kept HI2CIN from working properly. I blocked that code and everything worked.
I'm proud to pass the baton to the next runner;). I, too, had a similar problem with incoming data a few years ago where my diagnostic code caused the problem rather than solving it. Technical came to the rescue then, as well.
 
Top