Curing a locked up i2c bus after hardware reset of the picaxe

matherp

Senior Member
If you have ever had the problem of i2c commands not working when starting a program (particularly after a hardware reset without a power on/off) then I may have a solution. This issue has been annoying me for some time until I finally put the effort in to understand and track down a solution.

The issue arises if an i2c slave is writing at the time of the master reset and happens to be holding SDA low at the instant the master (picaxe) is reset. In this case the normal i2c command for resetting the internal state of the i2c slave (master issuing a start command which includes pulling SDA low) may not work.

The solution is as follows:

Before initialising the picaxe i2c hardware set SDA as an input and test for SDA low.
If it is low then set the SCL (SCK) pin as an output
Using a frequency not more that the i2c bus speed the slowest peripheral can handle, toggle the SCK pin low and then high until SDA goes high (i.e. clock out any remaining bits of the write from the peripheral). This cannot take more than 8 clock cycles - if it does then there is some other issue.

Once SDA is high then issue the hi2csetup command and all should work perfectly.

I've now installed this fix in all my programs and had no further lockups.

Hope this helps

Best regards

Peter
 

westaust55

Moderator
Thanks for posting that information which just may prevent one future question on this forum.

It would even be worth posting in the Finished projects area as your above comments with a code snippet for others to cut and paste. Just state which PICAXE the code snippet is for and the possible need to alter the pin addressing details for other chips.
 

BillyGreen1973

Senior Member
I wonder if this could be implemented, by Rev-Ed, into the compiler, so when a user issues the hi2csetup command it first makes sure the SDA and SCL lines are at the correct state, and apply the above fix if not.
I think this would make for a more reliable I2C setup for educational users.

Great work matherp. Thanks ;)
 

Technical

Technical Support
Staff member
It's not easy to add into the compilers, but we can certainly add it as an example in the manual as it is very useful.
 

westaust55

Moderator
It's not easy to add into the compilers, but we can certainly add it as an example in the manual as it is very useful.
I think that folks sometime forget is that the PIC microcontroller which form the core of the PICAXE chips have a relatively small Program memory capacity into which Rev Ed must shoe-horn the bootstrap routine, the BASIC interpreter program, and the users tokenised BASIC program.

In the case of the 18X and 18M2 that total program space is 4 kBytes of which 2 kBytes is allocated to the users program.
In the case of the 28X1 and 40X1 that total program space is 8 kBytes of which 4 kBytes is allocated to the users program.
For the earlier 28X2 and 40X2 that total program space is 32 kBytes of which 16 kBytes (as 4 x 4kB slots) is allocated to the users program.
So certainly for the earlier chips space is quite limited.

When we think that the early home computers such as the Commodore C-64 had a BASIC interpreter in 8 kBytes which did not include such commands for control of features such as Servos, PWM, i2c, SPI, etc then it is a credit to Rev Ed that we have so much “power”/capability within such a small package.

Even using the PE to add the code as part of the tokenised BASIC program downloaded for every program which includes an i2c setup command means complexities to determine if the i2c system is required for a program, and account for the extra bytes of program to be added which some users may not wish to bother with - until they have a problem.
 
Last edited:

abangyazan

New Member
Hi all,
this is my first posting in this forum... I had similar I2C bus locked up, so I follow matherp suggestion and it worked!

Here's my simple program to share (I used this on a 20M2):
Code:
Init_SDA:
	pause 1000

	input b.5

	if pinb.5=1 then
		sertxd("SDA is high",13,10)
		b0=8
		do
			pulsout B.7,150
			pause 20
		loop while pinb.5=1
		sertxd("Done..!",13,10)
		pause 500
		'check again...
		if pinb.5=0 then
			sertxd("SDA is now low",13,10)
		endif
	else
		sound c.1,(116,5)
		sertxd ("SDA is low",13,10)
	endif
	
RETURN
 
Top