' F:\PICAXE\SERVO CONTROLLER\SERVO_CONTROLLER.BAS
'===============================================================================
'
' S E R V O C O N T R O L L E R F O R R / C M O D E L S
'
'
' VERSION 1.0 30th October 2008 © A.F.Bond 2008
'
' Private and Educational use only is permitted
' Commercial use of this software is prohibited.
'===============================================================================
' This module was developed for the control of guns and cranes mounted on the
' decks of model boats, but aircraft, military and robotics modellers etc will
' doubtless find other applications for it. It combines the functionality of an
' R/C switch, a servo-slower and a servo stretcher in a unit whose footprint is
' not much larger than a standard servo.
'
' The R/C switch function detects joystick positions either side of a centre
' deadband and sets the servo moving in the appropriate direction. Releasing the
' stick (to centre) at any time stops the movement and holds the position. The
' traverse rate of the servo can be set to take up to approximately 10
' seconds from end-to-end. The end of travel limits for both clockwise and
' anticlockwise can be set by the user. Also, if the servo can cope with being
' (mechanically) over-driven, the usual +/-45 degrees swing can be extended up
' to a full +/-90 degrees.
'
' NOTE: In the description below be aware that PIN1, PIN2 etc are virtual
' pins and not to be confused with the device's phyical pins, which in PIC
' parlance are refered to as 'legs'
'
'===============================================================================
'HARDWARE DEFINITIONS
symbol jumper_link = pin4 'exactly what it says!
symbol push_button = pin2 'exactly what it says!
symbol servoh = 0 'pin0 'note spelling 'servo' is a reserved word
'VARIABLE DEFINITIONS
symbol signal_input = w0 'from r/c receiver
symbol servo_position = w1 'exactly what it says!
symbol delta = b4 'no. of 5uSec steps the servo moves by each time
symbol loops = b9 'no. of times round main loop before servo moves
symbol kount = b5 'for general purpose counting
symbol anticlockwise = b6 'movement direction flag
symbol clockwise = b7 'movement direction flag
symbol rate = b8 'traverse rate set by potentiometer
symbol anticlockwise_limit = w5 'end of servo angular travel
symbol clockwise_limit = w6 'end of servo angular travel
'CONSTANT DEFINITIONS 'USER MAY ADJUST DEADZONE & HYSTERSIS VALUES
symbol deadzone = 20 'region in which joystick movement has no effect
symbol hysteresis = 2 'prevents chatter at switching point
'DERIVED CONSTANTS 'BUT MUST LEAVE THESE ALONE !
symbol anticlockwise_trip = 300+deadzone '300=stick centre
symbol anticlockwise_release = anticlockwise_trip-hysteresis
symbol clockwise_trip = 300-deadzone '300=stick centre
symbol clockwise_release = clockwise_trip+hysteresis
'CHIP PROGRAMMING DIRECTIVE (only executed when program is loaded into chip)
'Pre-load non-zero values into EEPROM storage locations 0 and 1
data 0,(100) 'set clockwise limit of travel to 45 degrees
data 1,(100) 'set anticlockwise limit of travel to 45 degrees
'========================= PROGRAM STARTS HERE ================================
'INITIALISATION
setfreq m8 'set 8Mhz operation to yield 5uSec resolution
'===============================================================================
' P O W E R U P C H E C K
'===============================================================================
if jumper_link=0 then 'is jumper fitted?
goto setup_clockwise_limit 'YES - enter set-up mode
else
read 0, delta 'NO - retrieve user settings from
clockwise_limit=300-delta 'non-volatile memory and enter main program
read 1, delta
anticlockwise_limit=delta+300
servo_position=300 'initialise servo to centre position
goto main
end if
'===============================================================================
'===============================================================================
' S E T U P
'===============================================================================
'MOVE SERVO DIRECTLY WITH POT POSITION (clockwise from centre only)
setup_clockwise_limit:
readadc 1,clockwise_limit 'read pot on PIN1's ADC
clockwise_limit=clockwise_limit*20/25 'scale pot value 0 to 200
delta=clockwise_limit 'save amount prior to offsetting
clockwise_limit=300-clockwise_limit 'limit now in range 100 to 300
pulsout servoh,clockwise_limit 'move servo to that position
pause 40 '20 mSec frame rate
if push_button=1 then 'is this setup finished?
goto setup_clockwise_limit 'NO - keep looping round
else
do 'YES
if push_button=1 then 'has button been released yet?
write 0,delta 'YES - store limit in NV memory
goto setup_anticlockwise_limit 'exit this loop to next setup
end if
loop 'NO - wait until button released
end if
'MOVE SERVO DIRECTLY WITH POT POSITION (anticlockwise from centre only)
setup_anticlockwise_limit:
readadc 1,anticlockwise_limit 'read pot on PIN1's ADC
anticlockwise_limit=anticlockwise_limit*20/25 'scale pot value 0 to 200
delta=anticlockwise_limit 'save amount prior to offsetting
anticlockwise_limit=anticlockwise_limit+300 'limit now in range 300 to 500
pulsout servoh,anticlockwise_limit 'move servo to that position
pause 40 '20 mSec frame rate
if push_button=1 then 'is this setup finished?
goto setup_anticlockwise_limit 'NO - keep looping round
else
do 'YES
if push_button=1 then 'has button been released yet?
write 1, delta 'store limit in NV memory
servo_position=anticlockwise_limit 'set position variable to match
'where servo now is
anticlockwise=1 'and set direction flag too
goto main 'exit this loop to next setup
end if
loop 'NO - wait until button released
end if
'===============================================================================
'===============================================================================
' M A I N P R O G R A M L O O P S T A R T S H E R E
'===============================================================================
main:
readadc 1,rate 'read pot on PIN1's ADC
rate=rate/25 'scale to 10 distinct values
'USER MAY ADJUST VALUES IN THE LOOKUP TABLE BELOW TO CUSTOMISE TRAVERSE RATES
'get traverse time data related to pot position
lookup rate,(2,1,2,1,2,1,2,1,2,4),delta
lookup rate,(9,4,7,3,5,2,3,1,1,1),loops
pulsin 3,0,signal_input 'check receiver input
'CHECK IF JOYSTICK POSITION EXCEEDS THRESHOLDS AND SET MOVEMENT FLAGS TO SUIT
if signal_input>anticlockwise_trip then
anticlockwise=1 'set to move
else
if anticlockwise=1 then
if signal_input<anticlockwise_release then 'hysteresis zone exceeded?
anticlockwise=0 'YES - cancel movement
end if
end if
end if
if signal_input<clockwise_trip then
clockwise=1 'set to move
else
if clockwise=1 then
if signal_input>clockwise_release then 'hysteresis zone exceeded?
clockwise=0 'YES - cancel movement
end if
end if
end if
'DETERMINE WHEN TO MOVE SERVO POSITION
if anticlockwise=1 then 'ANTICLOCKWISE MOVEMENT
if servo_position>clockwise_limit then 'reached the limit yet?
inc kount 'NO - increment loop counter
if kount>=loops then 'loop counter reached target?
servo_position=servo_position-delta 'YES - alter servo position
kount=0 'then reset loop counter
end if
end if
end if
if clockwise=1 then 'CLOCKWISE MOVEMENT
if servo_position<anticlockwise_limit then 'reached the limit yet?
inc kount 'NO - increment loop counter
if kount>=loops then 'loop counter reached target?
servo_position=servo_position+delta 'YES - alter servo position
kount=0 'then reset loop counter
end if
end if
end if
'NO MOVEMENT REQUIRED
'if both flags zero, program
'drops through to this point
'REFRESH SERVO POSITION (whether moved or not)
pulsout servoh,servo_position
goto main 'loop round again
'===============================================================================