toggle and servo - need help

AlbertZ

Senior Member
What I want to be able to do is toggle between auto and manual modes using the “A” button on the transmitter. When in “auto” mode, the servo should just rotate slowly back and forth. When in “manual” mode, I should be able to move the servo left and right using buttons “B” and “D”.
However, here is what is happening. When powered up, the board is in “manual” mode by default. When I press the “B” and “D” buttons, the servo initializes but then does not move while I keep the button pressed. I can alternate pushing the buttons, but all it does is initializes the servo to its start position. Note: the receiver output goes high when the corresponding button on the transmitter is pressed.

Even more vexing is what happens when I try to toggle back and forth between “auto” and “manual”. The first push on button “A” takes me into “auto” mode and the servo does what it is supposed to do – sweeping slowly back and forth. But when I push the “A” button again, nothing happens if I push the button while the servo is executing a sweep. If I am lucky enough to push the “A” button at its start position (presumably when the program returns to main) it will toggle and stop rotation. But this is very iffy and I can catch it maybe once every ten tries. The idea is to be able to toggle B.7/ C.7 while the servo is executing a sweep. (see lines 75 and 82)
The strange thing is that the program seems to work as it should when I run it in the simulator.
Code:
'******************18M2 sentinel.bas****************
'Version 1.2
'AJZ/August 2015
'This is code for the Super Sentinel using the CHI030A
'PICAXE 18 standard project board
'The sentinel is controlled by a 4 channel transmitter/receiver
'When the Channel button on the transmitter is pressed,
'the corresponding channel on the receiver goes high
'Channel A toggles the turret between auto & manual mode
'Channel D drives the turret left
'Channel B drives the turret right
'Channel C fires the gun
'turret rotation is made using a standard servo
'In addition the sound of an alien recording is played during rotation

'===Constants===
symbol abit = 500			'sets short pause interval
symbol atic = 30			'sets servo pause to limit servo speed

'===Variables===
Symbol Chan_A = pinC.2		'Assign receiver channel A to Port C.2
Symbol Chan_B = pinC.0		'Assign receiver channel B to Port C.0
Symbol Chan_C = pinC.6		'Assign receiver channel C to Port C.6
Symbol Chan_D = pinC.1		'Assign receiver channel D to Port C.1
Symbol slave  = pinC.7		'Assign auto-rotate latch to Port C.0
					'pin B.7 & C.7 are jumpered together

symbol motor    = B.0	      'output to servo
symbol master   = B.7		'toggles auto mode on & off
symbol LED      = B.1	      'fires LED
symbol beep     = B.3	      'makes "alien recording" noise	
symbol chirp    = B.2    	'makes "strange alien" noise
symbol gun      = B.4         'makes "alien machine gun" noise

'===Directives===
#com 1				'specify serial port
#picaxe 18M2			'specify processor
'#no_data				'save download time
'#terminal of			'disable terminal window

'============== Begin Main Program ==========================
dirsB = %11111111			'all outputs
dirsC = %00000000			'all inputs


main:
If Chan_A = 1 then		'press "A" on xmtr
	toggle master		'toggles outpin B.1 between Hi/Lo
end if
pause atic
If slave = 1 then			'jumper between B.7 & C.7
	gosub auto
	end if
if Chan_D = 1 then		'press "D" on xmtr
gosub manleft			'manually rotate turret left
	end if
If Chan_B = 1 then		'press "B" on xmtr
gosub manright			'manually rotate turret right
	end if
If Chan_C = 1 then		'Chan "C" button is pressed on xmtr
	gosub shoot    		'execute shoot sub-routine
	end if
pause abit
goto main

auto:
high chirp				'activate "strange alien" sound
pause abit				'a momentary pulse activates
low chirp				'a 30 second sound bite
servo motor, 90			'pre-positions servo
pause abit				'0.5 sec delay
for b1 = 90 to 210		'sets travel limits
servopos motor, b1		'sweeps servo left
pause atic				'controls servo speed
	if Chan_A = 1 then	'press "A" on xmtr
		return
		end if
next b1				'until travel limit is reached
for b1 = 210 to 90 step -1	'reverses travel limits & direction
servopos motor,b1			'sweeps servo right
pause atic				'controls servo speed
	if Chan_A = 1 then	'press "A" on xmtr
		return
		end if
next b1				'until travel limit is reached
return				'continue until B.1 is toggled

manleft:
high beep				'activate "alien recording" sound
pause abit				'a momentary pulse activates
low beep				'a 30 second sound bite
servo motor,90			'pre-positions servo
pause abit				'0.5 sec delay
for b1 = 90 to 210		'sets travel limits & direction
servopos motor,b1			'pulses motor left
pause atic				'controls servo speed
	if Chan_D = 0 then	'until button is released
	goto main
	end if
next b1				'or until travel limit is reached
pause abit
return

manright:
high beep				'activate "alien recording" sound
pause abit				'a momentary pulse activates
low beep				'a 30 second sound bite
servo motor,210			'pre-positions servo
pause abit				'0.5 sec delay
for b1 = 210 to 90 step -1	'sets travel limits and direction
servopos motor,b1			'pulses motor right in increments
pause atic				'controls servo speed
	if Chan_B = 0 then	'until button is released
	goto main
	end if
next b1				'or until limit is reached
pause abit
return

shoot:
high gun				'take pin B.4 high
pause 100				'a short pulse plays entire sound bite
low gun				'take pin B.4 low
for b0 = 1 to 3			'entire sound bite is about 3 seconds
	high LED			'so we flash the LED at 0.5 sec intervals
	pause abit
	low LED
	pause abit
next b0
return				'finished firing sequence
View attachment Wiring Diagram 3.1.PDF

DSC00197.JPG

Any thoughts or suggestions would be most appreciated.
Also attached is the wiring diagram.
 

inglewoodpete

Senior Member
I have not studied your code very closely but I can see a lot of Pause abit (500mS) commands. During these periods, the PICAXE will not be checking or responding to the input switches. Could this be at the core of some of your problems?

I also noticed that you have a "GoTo Main" command in each of the ManLeft and ManRight subroutines. The ONLY way to exit a subroutine is via a Return statement, otherwise the return address stack is not managed correctly. A "GoSub" command puts the return address on the call stack so that the return statement knows the address to resume execution from.
 

AlbertZ

Senior Member
I have not studied your code very closely but I can see a lot of Pause abit (500mS) commands. During these periods, the PICAXE will not be checking or responding to the input switches. Could this be at the core of some of your problems?
This could well be the reason that I am not able to interrupt the "auto" sub-routine. I was not aware that the program does not respond to inputs during the pauses. With that being the case, do you have any suggestions how I can interrupt the "auto" sub-routine in order to toggle B.7.

I also noticed that you have a "GoTo Main" command in each of the ManLeft and ManRight subroutines. The ONLY way to exit a subroutine is via a Return statement, otherwise the return address stack is not managed correctly. A "GoSub" command puts the return address on the call stack so that the return statement knows the address to resume execution from.
Good catch. Yes I was aware of this because I had a goto in the "auto" sub-routine and it was generating stack errors. Once again, since Manleft and Manright are loaded with pause commands (in order to slow the servo down) are there any suggestions for manually moving the servos using buttons B and D. I am beginning to think that a motor might be a better choice in this application than a servo. I'm going to remove the pause commands in these two sub-routines and see if I can make the servo move with the buttons.
 

AlbertZ

Senior Member
One way is to do 500 little pauses and check for buttons in between each ...
Not sure how to do that. Do you have a code snippet?

No matter what I do, B.7 will not toggle while the program is executing the for...next commands in the "auto" sub-routine.

Meanwhile, I took out the conditional if...then statements in the manleft and manright sub-routines and got very sporadic movement of the servo.

Either I have a funky servo or a motor might be a better device for this application.
 

inglewoodpete

Senior Member
What you want to do can be done with a PICAXE. The problem you face is that the software sophistication needs to be a couple of levels higher than where it is at the moment. You will need to modify the main loop of your program so that it runs faster. That means getting rid of almost all pause statements. The main loop itself becomes an integral delay in itself (with all of things the main loop will have to do, it may take a minimum 5mS to complete each loop). Each function (like controlling each servo) will use its own loop counter and, when the counter expires, steps the servo to the next point before the counter/timer is reinitialised for the next step. So the main loop decrements all of the servo or task timers, checks inputs, checks for expired timers and takes actions as required for each task. Multitasking, PICAXE style. As I said before, it requires quite a sophisticated program to do this.

I built the electronics and software for the robotic figure in the attached photo (2009). That robot used 5 servos: 2 x arms, waist, neck and eye swivel. I haven't looked at the software for several years but I think it could move all servos at the same time. Eg. 'Walking': swinging its arms with waist and neck moving in opposite directions so the torso appeared to 'swagger' a bit. The water also 'squirts' via a randomly flashing white LED in the nozzle. So quite sophisticated things can be done with a PICAXE.
Man1_LoRes.JPG
 

AlbertZ

Senior Member
What you want to do can be done with a PICAXE. The problem you face is that the software sophistication needs to be a couple of levels higher than where it is at the moment. You will need to modify the main loop of your program so that it runs faster. That means getting rid of almost all pause statements. The main loop itself becomes an integral delay in itself (with all of things the main loop will have to do, it may take a minimum 5mS to complete each loop). Each function (like controlling each servo) will use its own loop counter and, when the counter expires, steps the servo to the next point before the counter/timer is reinitialised for the next step. So the main loop decrements all of the servo or task timers, checks inputs, checks for expired timers and takes actions as required for each task. Multitasking, PICAXE style. As I said before, it requires quite a sophisticated program to do this.

I built the electronics and software for the robotic figure in the attached photo (2009). That robot used 5 servos: 2 x arms, waist, neck and eye swivel. I haven't looked at the software for several years but I think it could move all servos at the same time. Eg. 'Walking': swinging its arms with waist and neck moving in opposite directions so the torso appeared to 'swagger' a bit. The water also 'squirts' via a randomly flashing white LED in the nozzle. So quite sophisticated things can be done with a PICAXE.
View attachment 18574
I have been thinking about your comment that the programming may require a couple of higher levels of sophistication. That's a bit disconcerting since I an a 73 year old retired steelworker, not a programming whiz. This may be above my pay grade! However, I am beginning to understand that controlling servos is a function of the Picaxe internal timers. That being the case, I can see how servo commands and pause commands when mixed together could cause an unsatisfactory result. I need to think about this and try to wrap my arms around how these timers work.

Meanwhile, I changed batteries (4.17 volts before - 4.7 volts after) and I managed to get the program to run in auto sort of. The servo sweep is much smoother, no jitters. In addition I can get it to toggle fairly consistently if I catch it at the end of a sweep cycle.

Manual operation is still a problem. Pressing the left and right buttons initializes the servo then causes erratic motion of the servo. Why should this be? I am using the same commands to move the servo that I am using in auto.

I am building a small breakout board for a L293D to experiment with using a small gear motor. It will require two more inputs for end of travel limits, but it seems to me that the function depends only on HI/LO commands which makes programming a bit simpler.
 

inglewoodpete

Senior Member
...I can see how servo commands and pause commands when mixed together could cause an unsatisfactory result.
The servo commands run in the background using internal timers and, for the most part, are not disrupted by the foreground code execution.

The Pause command is a foreground task. For simple programs a Pause command can be fine. The 'Pause' problem occurs when you want a program to interact with 'real world' input like the buttons you have. My personal preference is to rarely, if ever, use the Pause command (or the GoTo command but that is another story).

Rosko mentioned one option to minimise the impact of a large pause: many small pauses, checking for a button press between each one. Eg.
Rich (BB code):
For LoopCount = 1 To 50
   If Chan_B = 1 Then   ' If the button is pressed...
      Exit  'Exit the loop before time has expired.
   EndIf
   Pause 10 '50 x 10mS pause = approx 500mS
Next LoopCount
A good power source is required to run a servo - especially several servos. A servo motor is made up of a motor and a controller, which takes feedback from the actuator position to determine the direction to power the motor, when required. This is quite demanding of the power source. I prefer not to use batteries but it can be done with fresh, good quality ones. Also, electrical noise from the servo motor must not be allowed to get into the microcontroller power, otherwise the chip can be reset. This may or may not be happening your case.
 
Last edited:

AlbertZ

Senior Member
Toggle between auto and manual

After some experimentation, I learned some things and managed to accomplish some things. In this post I want to discuss the toggle/auto function. I'll deal with the manual operation in a separate post in order to avoid confusion. In the "auto" sub-routine I commented out both sets of if...then commands since they seemed to have no effect whatsoever on being able to toggle on command. I then ran the program and button "A" indeed toggles the program into auto. Pressing the "A" button then has no effect until just before the "auto" sub-routine is executed. If pressed just before the sub returns to main, I can get the program to toggle every time. I can live with that, although I still don't really understand why. Here is the "auto" sub-routine code:

Code:
auto:
high chirp				'activate "strange alien" sound
pause abit				'a momentary pulse activates
low chirp				'a 30 second sound bite
servo motor, 80			'pre-positions servo
'pause abit				'0.5 sec delay
for b1 = 80 to 220		'sets travel limits
servopos motor, b1		'sweeps servo left
pause atic				'controls servo speed
	'if Chan_A = 1 then	'press "A" on xmtr
	'exit
	'end if
next b1				'until travel limit is reached
for b1 = 220 to 80 step -1	'reverses travel limits & direction
servopos motor,b1		'sweeps servo right
pause atic				'controls servo speed
	'if Chan_A = 1 then	'press "A" on xmtr
	'exit
	'end if
next b1				'until travel limit is reached
return				'continue until B.1 is toggled
By the way, I took out the 30 msec pause just to see what would happen. The result is that the servo sweeps much faster but I still cant toggle until the end of the sub-routine. I mention this because I am still trying to get my arms around why shorter pauses will accomplish the result I was looking for i.e. interrupting the sweep and toggling on command.
 

AlbertZ

Senior Member
Manual servo operation

I was stumped as to why the servos would not respond to a right and left button push. They would pre-position as called for by the servo command, then just sort of sit in on spot and "quiver" for lack of a better term. I had used the code snippet before to move servos so it seemed to me that the if...then construct was somehow muddying the water. So I commented them out and low and behold the servo sweeps left or right depending on which button is pushed. So it would seem that all is well now. Not so fast...........

When I push "B" or "D" to initiate manright or manleft it executes a full sweep and returns to main (as it should). The problem is that I want to be able to stop the servo at any point along its path. This is what has me stumped. Once the for...next routine is initiated, how do you interrupt it? Is it even possible using a Picaxe? How will shortening the pause length help if the fundamental problem appears to be the if...then construct?

Please help

Code:
manleft:
high beep				'activate "alien recording" sound
pause abit				'a momentary pulse activates
low beep				'a 30 second sound bite
servo motor,90			'pre-positions servo
pause atic				'30 msec delay
for b1 = 90 to 210		'sets travel limits & direction
servopos motor,b1			'pulses motor left
pause atic				'controls servo speed
	'if Chan_D = 0 then	'until button is released
	'exit
	'end if
next b1				'or until travel limit is reached
pause abit
return
 
Top