18X and AXE033 servo problems

Silkjc

New Member
Hi all.
I'm attempting to control a sevo motor off the output pins of my 18X chip. The chip is wired to the AXE033 LCD and works perfectly. The servo is connected to it's own 4xAA battery back with the common ground connected to the Picaxe ground. The Picaxe is powered by a mains regulated 5v through a 7805 and transformer.

My problem is that if I use the servo or servopos command -anywhere- in the code, regardless of if I even have the motor connected or not, my Axe033 which is connected via ic2 gets garbled:

It remains garbled like this until new LCD write commands are sent to overwrite the garble, but will quickly return to this state, sometimes not even all at once but gradually with different characters changing.

My code is as follows (lotsa useless garble in there but I wasn't sure if removing anything would be wise xD):
Code:
symbol seconds 	= b1 
symbol mins 	= b2
symbol hour 	= b3
symbol day		= b4
symbol date 	= b5
symbol month 	= b6
symbol year 	= b7
symbol DS1307 	= %11010000 'i2cslow, i2cbyte
symbol AXE033	= %11000110	'i2cslow, i2cbyte

init:
b0=0 'Intially start in display mode 0, saved in register 80
poke 80,b0



'REGISTERS:
' 80 - Current display mode
' 81 - Dosage 1 quanitty
' 82 - Dosage 2 quantity
main:
 	w1=0
 
	i2cslave DS1307, i2cslow, i2cbyte 'Initialise Axe033 for reading from DS1307 registers
	readi2c 0, (seconds,mins,hour,day,date,month,year) 'Reads in the timing data



	'Dosage Calculation - Pretty important...right?
{	readadc 1,b0 'Read the current dial setting (pot), range is 0-255
	readadc 0, b4 'Read the second potentiometer
	
	'Dosing will occur once a day
	'Increments of size: 255/10
	b0=b0/10
	b4=b4/10
	poke 81, b0 'Save the amounts we're dosing to the registers
	poke 82, b4 'Decimal accuracy will be clipped by integer division

}





 	i2cslave AXE033, i2cslow, i2cbyte ' Initialise Axe033 for writing time/date to LCD
	
	''''''''''''''''''''
	'MODE 0 DISPLAY TIME
	''''''''''''''''''''
{	peek 80,b0
	if b0=0 then
		writei2c 0,(254,128,255) ' Set the cursor to the very start
		pause 10

		bcdtoascii seconds, b8,b9 'Converts the bcd into ascii values
		bcdtoascii mins, b10,b11
		bcdtoascii hour, b12,b13 
		writei2c 0,(" Time:",b12,b13,":",b10,b11,":",b8,b9,255) 'Write the ascii to the LCD
		pause 10 'Pause after every write
		writei2c 0,(254,192,255)
		pause 10
		writei2c 0,("   Dosing ON.",255)
		
		high 5

	end if
}
	
	''''''''''''''''''''''
	'MODE 1 DISPLAY DOSAGE
	''''''''''''''''''''''
	peek 80, b0
{	if b0=1 then
		peek 81,b0
		peek 82, b4
		bintoascii b0,b12,b1,b2
		bintoascii b4,b12,b5,b6

		writei2c 0,(254,128,255)
		writei2c 0,("Dose 1:",b1,b2," ml/day",255)
		pause 10
		writei2c 0,(254,192,255) 'Set the cursor to the second line
		writei2c 0,("Dose 2:",b5,b6," ml/day",255)
		pause 10
		
		low 5

	end if
}	


	''''''''''''''''''''''
	'MODE 2 FORCE DOSAGE
	''''''''''''''''''''''
	peek 80, b0
{	if b0=2 then
		writei2c 0,(254,128,255)
		writei2c 0,("Force dose:",255)
		pause 10
		writei2c 0,(254,192,255) 
		writei2c 0,(" Dose1   Dose2 ",255)

	end if
}

	'Count the pushes of displaymode button, incrementing register 80 
	count 6,500, b0
	if b0 > 0 then displaySwitch






'Handle battery charging
{

'HACK FIX NEEDS TO BE WORKED OUT
low 5
readadc 2, b0 'Read in the current battery level
high 5
debug b0
if b0 < 70 then 'For 5v, b0 of 90 is fully charged
	high 5    'High 5v to battery
	high 6    'High to charging LED indicator
else
	low 5
	low 6
end if
}



'Handle Servo Control
{
'servopos 7, 42
'pause 1150
'servopos 7, 222
'pause 1150 
}









goto main


'Increment count register 80, or reset to 0 if last mode reached
displaySwitch:
{	
	peek 80, b0
	b0=b0+1
	writei2c 0,(254,1,255)
	pause 10
	if b0>2 then 
		b0=0

	end if
	poke 80, b0
	debug
	
}
goto main
Any suggestions would be great, I'm certain it has nothing to do with my actual servo as disconnecting it makes no difference. Perhaps something to do with ic2 and the servo command? Despite the garble, when I do include the servo commands they do work and the servo moves fine.
 
Last edited:

BeanieBots

Moderator
According to Appendix A, only background hardware I2C will be affected by servo.

Lots of peeks and pokes in there!
The first thing to do is cut the code right back.
Do a very basic loop which includes ONLY a simple text write to the display and a servo command. Nothing more.
 

Silkjc

New Member
Hi Beanie,
After stripping down the code to just this:

Code:
symbol DS1307 	= %11010000 'i2cslow, i2cbyte
symbol AXE033	= %11000110	'i2cslow, i2cbyte

init:
servo 7, 100

	
main:
	i2cslave AXE033, i2cslow, i2cbyte ' Initialise Axe033 for writing time/date to LCD
	writei2c 0,(254,128,255)
	writei2c 0,("Force dose:",255)
	pause 10
	goto main
I still get the same garbled display. So i'm guessing there is something wrong with my circuit. Are there any obvious errors in the above code?
 

hippy

Ex-Staff (retired)
AFAIK, the SERVO command should not adversely affect I2C used in this way; if an internal servo handler interrupt occurred it would leave the I2C 'suspened, as it was' until it returned which is within I2C specifications.

Two things you can try, 1) remove the SERVO command, and 2) try the SERVO command on a different pin ( not 1 or 4 which are used for I2C ! ) and see what happens in both cases.
 

BeanieBots

Moderator
Nothing obvious in your code.
Like Hippy, I can see no reason why servo should effect I2C.
Unlike serial data which is timing dependant, I2C is clocked and can (in theory) be stopped and started at will even during a data exchange.

Worth trying another pin as suggested.
If it's a hardware fault, the odds on having a similar fault on a different pin are slim. However, it could be a firmware bug.
(servo and I2C share the same port)

Unfortunately I don't have a spare AXE033 to hand at the moment which is unusual because they are excellent as debug tools.

If you have a 'scope (or even a simple DVM), try a simple program which toggles OP 7 and see if there is anything happening on either SDA SCL pins.

Double check that your 4k7 pull-ups really are connected to the I2C pins.
 

Technical

Technical Support
Staff member
Your i2cslave command should not be in the loop, it reconfigures the pin i/o status to the i2c required status. Every time it is processed it resets the i2c pins and so this in theory could create garbage when mixed up with servo pulses. It should be one line after init: , there is no need to repeat it in the loop. Does that sort things out?

We've not tried it, but if you then still have problems you may be able to workaround by a 'low 7' command before the writei2c and then 'servo 7,x' command after again - does that resolve the issue?
 
Last edited:

Silkjc

New Member
Thanks everyone. I tried all your suggestions and thankfully the one that worked was the last one, as suggested by Technical. Setting pin 7 to low before any writes worked. Thanks for your help :) I'll have some time to do further testing tomorrow.
 

BeanieBots

Moderator
If you also setup servo on pin 6 (or some other available OP except the I2C lines), but still do a low 7 before I2C, does the problem re-appear?
 

Silkjc

New Member
Not quite sure what you mean, do you mean adding an initialised servo pulse on 6 like this:
Code:
init:
servo 7, 100
servo 6, 100
	
main:
	i2cslave AXE033, i2cslow, i2cbyte ' Initialise Axe033 for writing time/date to LCD
	low 7
'low 6
	writei2c 0,(254,128,255)
	writei2c 0,("Force dose:",255)
	pause 10
	servopos 7, 150
	servopos 6, 100
	pause 1000
	goto main
If I have the low 6 uncommented the problem is fixed. If it is removed the garbled display comes back.
 

BeanieBots

Moderator
That is what I meant.
The fact that ANY active servo pin demonstrates that there is a servo/I2C interaction which Rev-Ed needs to look into.

I'd guess that this relates to changing the port direction when servo requires output and I2C requires input.

Be aware that the work-around of making the servo pin low will leave your servo 'limp' for the duration and might cause a glitch when it comes back up.
It's not ideal.
 

Silkjc

New Member
Thankfully this application of my servo calls for it to be set limp for long durations and perform one rotation every day (timed micropump), so this hack fix should save power. What kind of glitch could be expected when turning the servo back on? It's rather important the servo position does not change unless commanded.
 
Last edited:

BeanieBots

Moderator
Whenever the servo command is executed, the counter/timer used to control position is reset. In applications where the command is within a tight loop (particularly one of <20mS), this can manifest as a slight twitching of the servo. The servopos command gets around this.
In your application, with a large dead time between updates, I would NOT expect it to a problem for you.
 
Top