Problem with output pin

vansav8r

New Member
Hi,
I wonder if I could seek advice again. I am fairly inexperienced programming picaxe and am playing with a stepper motor, rotary encoder and display to move a camera on a linear rail to do some focus stacking. The stepper, encoder and display all work well the process is to input a number of steps for the stepper motor using the encoder then input a number of times to repeat the steps again using the encoder.
Between each batch of steps I want to pause and trigger the camera to take a shot then proceed to the next batch of steps. (gosub CAMERA)
I need an output from the chip to drive an opto isolator and at present just have an LED connected to B.5, I am expecting a flash each time the program pauses between batches of steps ie triggering the camera but instead I am getting an unusual sequence of flashes depending on how many steps and shots I request.

If I set 6 steps and 9 shots the led flashes on 1,3,5,7,9 shots
if I set 9 steps and 9 shots the led flashes on 2,3,6,7 shots
If I set 15 steps and 9 shots the led flashes on 1,2,5,6,9 shots
I have left the shots at 9 for some consistency anything different would give different results.

I am tearing my hair out on this one and due to limited knowledge have hit a brick wall.
I have included my code, I'm suspecting some problem with dirs or pins statements but not sure, any help would be much appreciated.
Jim

Code:
'===================================
'ROTARY ENCODER READER AND STEPPER MOTOR CONTROLLER Picaxe 18M2

INSTRUCTIONS:
#Picaxe 18M2	' specify the PICAXE the program code is for
#No_Data		' do not download data EEPROM values


'=====================================

Pause 500
MESSAGE:
setfreq M4
serout C.7,n2400,(254,128,"  FOCUS STACKER")
serout C.7,n2400,(254,192," XXXXXXXXX  2018")
Pause 5000 
serout C.7,n2400,(254,1)
serout C.7,n2400,(254,128,"Each Step=0.04mm")
serout C.7,n2400,(254,192," Table Travel")
pause 5000
setfreq M32
let dirsC=%11001000  	   'set pin 3 & 7 as outputs

b10=0 b11=0 b2=0		   'b10 = steps  b11 = shots
gosub STEPREQUEST
gosub ENCODER

TEST1:
if b10>0 then 	'test if STEPREQUEST is complete
b11=b1		'set b11 as no of shots
goto CHECKER endif
b10=b1		'set b10 as no of steps
if b10>0 then	'if STEPREQUEST is complete then perform TEST2
goto TEST2 endif

TEST2:
gosub SHOTREQUEST
gosub ENCODER

CHECKER:		'report steps and shots
setfreq M4
serout C.7,n2400,(254,1)
serout C.7,n2400,(254,128)
serout C.7,n2400,("Step ",#b10," Shot ",#b11)
serout C.7,n2400,(254,192,"Press to Start")
setfreq M32

gosub PUSHBUTTON1	'check for pushbutton enter

REPEAT:		'repeat sequence

w0=b10*40		'this bit converts steps to distance travelled
w0=w0/10
bintoascii w0,w1,w2,w3

gosub STEPPER
gosub PUSHBUTTON1	'check for pushbutton enter
if pin0=0 then	'if encoder button pushed then repeat
goto repeat endif
end

STEPPER:	setfreq M4
		serout C.7,n2400,(254,1)
		serout c.7,n2400,(254,128)
		serout c.7,n2400,("TRAVEL = ",w1,".",w2,w3,"mm")	'travel distance report
		setfreq M32	
		
		let dirsB=%00001111		'set output pin
		
		for b4 = 1 to b11			'number of shots
		for b3 = 1 to b10 		'start a for...next loop
		gosub lstep				'call left step sub-procedure
		next b3				'next loop
		pause 10000                 	'PAUSE BETWEEN SHOTS
		gosub CAMERA
		next b4


		for b4 = 1 to b11			'return to start position
		for b3 = 1 to b10			'start a for...next loop
		gosub rstep				'call right step sub-procedure
		next b3				'next loop
		next b4

		setfreq M4
		serout C.7,n2400,(254,1)
		serout C.7,n2400,(254,128," Job Complete")
		low 4
		serout C.7,n2400,(254,192," Press to repeat")
		setfreq M32
		return

lstep:	'left step
		High 4				'switch on 12v to stepper
		let b1 = b1 + 1			'add 1 to variable b1
		setfreq M4
		serout c.7,n2400,(254,192,"Shot No  ",#b4)
		setfreq M32
		gosub stepit			'do the step
		return

rstep:	'step right
		let b1 = b1 - 1 			'subtract 1 from variable b1
		setfreq M4
		serout c.7,n2400,(254,192,"Return to Home")
		setfreq M32
		gosub stepit			'do the step
		return

stepit:						'stepper motor control
		let b1 = b1 & %00000011 			'mask lower two bits of b1 -- resets b1 back to 0 after reaching 4
		lookup b1,(%1010,%1001,%0101,%0110),b2	'lookup code into b2
		let pinsB = b2					'output b2 onto control lines
		return

STEPREQUEST:
setfreq M4
serout C.7,n2400,(254,1)
serout C.7,n2400,(254,128,"No of Steps ")
serout C.7,n2400,(254,192,"Press to enter")
setfreq M32
return

SHOTREQUEST:
setfreq M4
serout C.7,n2400,(254,1)
serout C.7,n2400,(254,128,"No of Shots ")
serout C.7,n2400,(254,192,"Press to enter")
Setfreq M32
return

ENCODER:
b1=0
setfreq M32               'set clock frequency
'b1 is output counter
'c.1=clk
'c.2=DT
'C.1=0 and c.2=0 = b0=0
'C.1=1 and c.2=0 = b0=2
'C.1=0 and c.2=1 = b0=4
'C.1=1 and c.2=1 = b0=6

main:		gosub read_c		'read the encoder
		if b0=0 then main		'test rotation?
		if b0=4 then goto CW	'start of a clockwise rotation
		if b0=2 then goto CCW	'start of a counter clockwise rotation
		goto main

CW:		gosub read_c		'is rotation CW
		If b0=4 then 		'wait for more
		goto CW		
		else
		if b0=0 then main		'return if rotation reversed
		endif
	
six:		gosub read_c		'read the encoder
		if b0=6 then 		'check if clockwise
		goto six
		else
		if b0=4 then CW		'if reverse rotation then goto cw
		
deux:		gosub read_c		'read the encoder
		if b0=2 then 		'check if clockwise
		goto deux			'wait for more
		else
		gosub read_c		'read the encoder
		if b0=6 then six		'if reverse rotation then goto six
		goto CWT			'clockwise complet?
		endif	
		endif
	
CWT:		B1=b1+1			'increment b1 +1
		gosub DISPLAY
		'debug
		goto main

CCW:		gosub read_c		'rotation is clockwise
		If b0=2 then 		'wait for more
		goto CCW
		else
		if b0=0 then main		'goto main if rotation reversed
		endif
	
six1:		gosub read_c		'read the encoder
		if b0=6 then 		'check if counterclockwise
		goto six1			'wait for more
		else
		if b0=2 then CCW		'if reverse rotation then goto ccw

deux1:	gosub read_c		'read the encoder
		if b0=4 then 		'check if counteclockwise
		goto deux1			'wait for more
		else
		gosub read_c		'read the encoder
		if b0=6 then six1		'if reverse rotation then goto six1
		goto CCWT			'counterclockwise complet?
		endif
		endif
	
CCWT:		if b1=0 then fin		'if b1 = 0 then fin
		B1=b1-1			'decrement b1-1
		gosub DISPLAY
fin:		'debug
		goto main	

read_c:	b0=pinsC			'reading pins c
		b0=b0 & %00000110		'mask c1 & c2
		gosub PUSHBUTTON
		return
DISPLAY:
		setfreq M4
		serout C.7,n2400,(254,141,"   ")
		serout C.7,n2400,(254,141,#b1)	'display encoder output
		setfreq M32
		return
PUSHBUTTON:	
		if pin0 = 0 then 
		pause 5000
		goto test1
		endif
		return
PUSHBUTTON1:
		low b.0 low b.1 low b.2 low b.3	'Switch off data lines to stepper controller
		do
		if pin0 = 0 then exit	'check for pushbutton on end of encoder
	      loop while pin0>0		'loop until pressed
		return		
CAMERA:
		High 5		'Trigger camera
		pause 3000		'short wait
		Low 5
		Pause 1000
		return
 

AllyCat

Senior Member
Hi,

I've not checked all through your program, but what you describe is often associated with a byte/word variable being changed "unexpectedly" by the program. So my eyes fell on the following.

Code:
w0=b10*40		'this bit converts steps to distance travelled
w0=w0/10
bintoascii w0,[B]w1,w2,w3[/B]
The first two lines are doing exactly the same as w0=b10*4 , is that what you intend?

But my main concern is the BINTOASCII, which will overwrite all the byte variables from b2 up to b7 (because w1 "overlays" b2,b3, etc), which are used elsewhere in the program. Also these "output" variables don't need to be words, only bytes (any ASCII value will fit in a single byte). Therefore, I would change the w1,w2,w3 to byte variables that aren't used elsewhere in the program, just to be safe, and see if it helps. ;)

Cheers, Alan.
 

PhilHornby

Senior Member
Also, this construct is decidedly 'iffy' :-

Code:
[COLOR=Black]PUSHBUTTON: 
            [/COLOR][COLOR=Blue]if [/COLOR][COLOR=Purple]pin0 [/COLOR][COLOR=DarkCyan]= [/COLOR][COLOR=Navy]0 [/COLOR][COLOR=Blue]then 
                  pause [/COLOR][COLOR=Navy]5000
                  [/COLOR][COLOR=Blue]goto [/COLOR][COLOR=Black]test1
            [/COLOR][COLOR=Blue]endif
            return[/COLOR]
Rather than using 'goto test1', you should set a 'flag' that can be tested by the caller. Otherwise, there is a danger of overflowing the 'subroutine stack' at some point. (I don't think this is the cause of the issue you are currently seeing though)
 

hippy

Technical Support
Staff member
I have not really looked at the code but it may be worth running it through simulation in PE6 to help determine why it is doing what it does, why it is not doing what you expect.
 

vansav8r

New Member
Hi thanks for the replies, I have altered the w0=b10*4 and in the bintoascii statement changed to unused byte variables instead of word variables I also changed the w0 and left it as b0 but as yet the program still has the same problem. I needed the w0 so that I could call up more than 64 steps of the motor if needed as 64 * 4 = 256 the limit of the byte variable.
The PUSHBUTTON routine I can change but as you say I dont think this is the problem.
Apologies for the messy code this is a somewhat first go + learning excersise
 

vansav8r

New Member
Sorry guys, this one was totally down to me, the problem was due to an incorrect connection to the picaxe board, the ground of the led was not connected to ground but to pin B3 (next to ground on the board) so hence the random nature of the led. I decided to poke around with my multimeter which unearthed the problem.
Thanks again for the suggestions.
Jim
 
Top