With a lot of help from this forum I have got my programme 'nearly' working. I struggle with various aspects of programming, mainly memory handling, word (and byte!) variables and the little bit of maths incorporated produces strange results that I cannot decipher.
My code probably does not follow good programming guidelines, it mostly works however, but the last few hours have resulted in backwards progress and I now realise that there are one or two problems that I do not have the skill to resolve.
The basic idea is that a pot will control the position of a servo, with the added complication that only partial travel of the servo might be used but the full travel of the pot will always will be. (i.e. scaled to suit the output range)
I would be really grateful if someone could look through my code and help me make sense of it, please...
Ian
My code probably does not follow good programming guidelines, it mostly works however, but the last few hours have resulted in backwards progress and I now realise that there are one or two problems that I do not have the skill to resolve.
The basic idea is that a pot will control the position of a servo, with the added complication that only partial travel of the servo might be used but the full travel of the pot will always will be. (i.e. scaled to suit the output range)
I would be really grateful if someone could look through my code and help me make sense of it, please...
Ian
Code:
; Focus Servo for underwater camera using 08M Picaxe
; Ian Phillips Oct 2010
;
; 1000 to 2000uS PWM. Servo needs 100 to 200 for 9 turns of feedback pot
; Setfreq m8 (or M32?) Might try increasing pulsout resolution later (with 08M2?)
;
; The full range of the input pot (0-255 ADC) is always to be used to cover the
; servo travel between the hi and lo endstop positions which have previously been set
; by the user (to suit different lenses).
;
; The two endstop positions and the scaling value have to be saved to NVR and only
; get changed when the 'Record' and 'Update' functions are used. A 'Centralise'
; routine puts the servo to mid travel and also puts in default scaling and endstop
; values so the user can use the pot to move to the endstop places that need recording.
;
Output 0 ; Servo signal (Pin 7)
Input 1 ; Focus Pot wiper (Pin 6) 5k Pot between 0V and +5V
Input 2 ; Update/Save momentary sw (Pin 5) Pull up resistor, switch takes input low
Input 3 ; Save End Posn momentary sw (Pin 4) Pull up resistor, switch takes input low
Input 4 ; Centralise momentary sw (Pin 3) Pull up resistor, switch takes input low
Symbol ADCVAL = w0 ; ADC reading (0 to 255)
Symbol Posn = w2 ; Servo Position. This value is for pulsout
Symbol Divi = w4 ; Divisor value for formula. To be stored in NVR
Symbol Offset = w6 ; Offset value for formula. To be stored in NVR
Symbol Span = b7 ; Difference between Hi and Lo servo positions
Symbol HiVal = b10 ; POSN value at Hi end of servo travel
Symbol LoVal = b12 ; POSN value at Lo end of servo travel
Main:
pause 20 ; Adjust this value to get pulse repetion rate to 20mS
if Pin3 = 0 then Goto Record ; Write current position/s value to memory
if Pin2 = 0 then Goto Update ; Write default equation values to memory
if Pin4 = 0 then Goto Centralise ; Puts servo to mid travel and installs default scaling and stops
if Pin3 =1 and Pin2 = 1 and Pin4 =1 then goto Normalop ; Normal operation
Goto Main
Normalop:
Read 3,Divi ; Divisor so get correct output scaling
Read 4,Offset ; Basically same value as one end stop
Readadc 1,ADCVAL ; Gives 0-255
Posn = ADCVAL*100/Divi+Offset ; Convert ADC number to value for servo
Pulsout Output0,Posn ; Send signal to servo
Goto Main
Centralise: ; Also 'resets' system to allow max travel
Pulsout Output0,150 ; Put servo to mid position for user setup (150 gives 1500uS)
Write 3,253 ; Default for Divisor (See note below)
Write 4,100 ; Default for offset
goto main
Record:
Readadc 1, ADCVAL ; I put this line in to 'refresh' value as seen in simulator
if ADCVAL <=150 Then WriteLowVal ; Store end (stop) positions for both ends of servo travel
if ADCVAL >150 then WriteHighVal ; Numbers are servo values created with default equation data
goto main
WriteLowVal:
Posn = ADCVAL *100/Divi + offset ; Another refresh just to be safe
Write 6, posn ; Write current servo value to memory
loval = posn ; Loval is now same as posn
goto main
WriteHighVal:
Posn = ADCVAL *100/Divi + Offset ; Another refresh to be safe
write 7, posn ; Write current servo value to memory
hival = posn ; Hival is now the same as Posn
goto main
Update:
Span = Hival-Loval ; New span range
Write 5, Span ; Put the span value in location 5
Divi = 25500 / Span ; Calculates new divisor based on the new end values
Write 3,Divi ; Put result in location 3
write 4,loval ; Save to NVR
goto main
;NOTES
; Scaling of the ADC to suit the Servo is by dividing the ADC reading by the difference between the
; two ends of the servo travel (defined here as the Span). The maximum Span is about 100 (200 minus 100)
; for a standard servo. Maximum ADC is 255, so 255/100 gives a divisor of 2.55 so ADC has to be x100 for
; Picaxe maths purposes.
; If only part of the servo travel is being used the span number will be smaller which results in a much
; bigger divisor value so Word variables will be involved.