PIC to Picaxe program conversion - simple servo drive

Hello to all, and thank you in advance for reading further...
Somewhat of a newbie here to Picaxe, but that definitely comes with a keenness to learn.
I am rather stuck, and would be most grateful of the some much needed help as I can then really start progressing and exploring further functionality.
I have tried to find an answer to this, but I now turn to the wealth of knowledge here.
Basically I have found a program written for a PIC chip, and want to ‘convert’ it to work within a Picaxe chip.
It’s a simple servo drive between 2 end points, with the end points being able to be set by the user.
So without too much further waffle I will include the program here, and would be so grateful if someone can talk/guide me through what needs changing for it to work on a Picaxe chip - hopefully an 08M2 if that's possible?.
Looking forward to hearing further, cheers for now.

Code:
'****************************************************************
'*  Name    : ServoLock                                         *
'*  Author  : Tarkan Akdam                                      *
'*  Notice  : Copyright (c) 2012 Tarkan Akdam                   *
'*          : All Rights Reserved                               *
'*  Date    : 20/06/2012                                        *
'*  Version : 1.6                                               *
'*  Notes   : 12F629                                            *
'*          : This circuit moves a standard RC servo between    *
'*          : two programmed and stored positions               *
'*          : Each position is selected by logic level on GP3   *
'*          : The Servo is disabled after 5 seconds             *
'*          : which is plenty of time for the servo to reach    *
'*          : the final positions requested.                    *
'****************************************************************
'*          :Circuit Pin Configuration                          *
'*          :GP3- ALARM IN - High is Position Two               *
'*          :GP0- Move Servo Up                                 *
'*          :GP1- Program Mode                                  *
'*          :GP2- Move Servo Down                               *
'*          :GP5- Servo Pulse Out                               *
'*          :GP4- HeartBeat LED                                 *
'****************************************************************


define OSC 4
DEFINE OSCCAL_1K 1


CMCON       = 7   'comparator off
WPU         = %00110111 ' Internal pull-ups = on
OPTION_REG  = %00001000 ' Pull-ups = yes, GPIO.2 = I/O, prescaler to WDT
INTCON      = %00000000  ' disable all interupts
GPIO        = %00000000 ' All outputs = 0 on boot
TRISIO      = %00001111 '  GP4 and GP5 output
IOC         = %00000000  'disable IOC interrupt

'**********************
'Constants
MaxPos  CON 262   'hard limits of servo movement - as measured for my servos
MinPos  con 68    

'**********************
'Variablles
ServoProgram    var gpio.1
ServoUp         VAR gpio.0
ServoDown       var gpio.2
ServoPulse      var gpio.5
LEDOut          var gpio.4
AlarmIn         var gpio.3


HeartBeat       var byte
TimeOut         var byte
Counter         var byte  
DataSaved       var byte  

PosTWO          var word   'stores the PosTWO position
PosONE          var word   'stores the PosONE position
ServoPosition   var word   'current position of servo
PrevPosition    var word   'old position of servo

'*****************************************
'read stored positions from eeprom before proceeding
read 00, word PosTWO   'PosTWO is stored addr 0,1
READ 02, word PosONE 'PosONE is stored at addr 2,3

'*****************************************
'make sure outputs and variables are how we want them
ServoPulse  =   0   'servo signal line to 0v
HeartBeat   =   0
TimeOut     =   0
DataSaved   =   0

' main program loop
main:

IF HeartBeat = 35   then        'flash heartbeat led
    HeartBeat = 0
    Toggle LEDOut          'toggle led
else
    HeartBeat = HeartBeat + 1
endif

'check if we are in program mode
if ServoProgram = 0 then gosub ProgrammingMode

'are we PosTWO or PosONE
if AlarmIn = 1  then
    ServoPosition   = PosTWO
else
    ServoPosition   = PosONE
endif

gosub ServoMove   

goto main

'************************************
'* This sub moves servo to programmed position
ServoMove:

IF ServoPosition = PrevPosition   then        'is servo position the same as previous
    IF TimeOut < 250 then TimeOut = TimeOut + 1 'then start TimeOut Counter
else
    TimeOut = 0                                'else reset timeout and save current position
    DataSaved = 0                               'reset eeprom flag
    PrevPosition  = ServoPosition
endif

IF TimeOut = 250 then goto skippulse   'if timed out skip moving servo                   

ServoPulse = 0      '0v signal - put signal line in to a known state before pulseout
pulsout ServoPulse, ServoPosition 

skippulse:      'jump here to not bother with pulse
pause 19   'wait 19ms


return  'go back


'****************************************
'* Programming Mode
ProgrammingMode:
LEDOut = 0 'Turn ON LED to show program mode

IF AlarmIn = 0 then
    IF ServoUp = 1 and ServoDown = 0 ThEN PosONE = PosONE + 1
    IF ServoUp = 0 and ServoDown = 1 ThEN PosONE = PosONE - 1
else
    IF ServoUp = 1 and ServoDown = 0 ThEN PosTWO = PosTWO + 1
    IF ServoUp = 0 and ServoDown = 1 ThEN PosTWO = PosTWO - 1
endif

IF PosTWO > MaxPos  then PosTWO = MaxPos      'lets make sure position is not outside
IF PosTWO < MinPos   then PosTWO = MinPos     'these defined hard limits
IF PosONE > MaxPos then PosONE = MaxPos
IF PosONE < MinPos then PosONE = MinPos

IF TimeOut > 249 then    'store values in to eeprom if we have reached timeout limit
    for Counter = 0 to 5  'Quick Flash LED - let user know we have saved the values
        toggle LedOut
        pause 100
    next Counter

    IF DataSaved = 0 then  'only write to eeprom if datasaved flag is 0   
        DataSaved = 1       'set flag to stop eeprom writes until position has changed 
        write 00, word PosTWO    'write the data to the eeprom
        write 02, word PosONE
    endif
endif


return  'go back

end
 

Buzby

Senior Member
Hi BrainStrain,

Have you already got a PICAXE and a servo wired up ?.

Although the PIC code could be re-worked for a PICAXE, it would be much easier to program from scratch.

See the servo command here : http://www.picaxe.com/BASIC-Commands/Digital-InputOutput/servopos/

The example code shown there ( and below ) does in 5 lines most of what those dozens of PIC codes do.

Code:
init:    servo 4,75    ; initialise servo
main:    servopos 4,75    ; move servo to one end
    pause 2000    ; wait 2 seconds
    servopos 4,225    ; move servo to other end
    pause 2000    ; wait 2 seconds
    goto main    ; loop back to start
Cheers,

Buzby
 

AllyCat

Senior Member
Hi,

That program is basically just another "dialect" of the BASIC language, so shouldn't be difficult to convert to PICaxe Basic. But without knowing the exact version (which doesn't look to be complete anyway) it will be difficult to convert the exact "numbers" or constants. Also, IMHO the programming looks rather "dumb"; to (need to) store a WORD value into EEPROM for a maximum value of 262 (when a byte can store up to 255) won't be necessary with PICaxe coding. ;)

A starting point is probably to define the pin connections: In the original program "GP0 - 3" are inputs and "GP4 - 5" outputs, but with a PICaxe (08M2), pin C.5 must be the Programming Input and C.0 the Programming Output. Thus, I would map C.0 to the LED (GP4) and the Servo Pulse (GP5) to C.1 (or perhaps C.2 as this is the hardware PWM output of the 08M2). The programming input (C.5) is probably best mapped to "GP1" (if needed) and the other input pins can be allocated in any way convenient for the layout / interconnections.

Then compare the original program with the similar PICaxe commands; in most cases you should find the PICaxe commands are almost the same, but easier to use than the original program. :)

Edit: Most of the "VAR" declarations won't be needed, but those that are would use the PICaxe SYMBOL command. The name of the "programming mode" subroutine might be confusing, perhaps better called "learn_{positions:}" in a PICaxe environment.

Cheers, Alan.
 
Last edited:
Hi BrainStrain,

Have you already got a PICAXE and a servo wired up ?.

Although the PIC code could be re-worked for a PICAXE, it would be much easier to program from scratch.

See the servo command here : http://www.picaxe.com/BASIC-Commands/Digital-InputOutput/servopos/

The example code shown there ( and below ) does in 5 lines most of what those dozens of PIC codes do.

Code:
init:    servo 4,75    ; initialise servo
main:    servopos 4,75    ; move servo to one end
    pause 2000    ; wait 2 seconds
    servopos 4,225    ; move servo to other end
    pause 2000    ; wait 2 seconds
    goto main    ; loop back to start
Cheers,

Buzby
Hi Buzby, and thank you for responding.
Totally appreciate the idea of keeping things simple, and indeed I didn't go into too much detail on the application this will be used for.
Once this is developed into a working project, I wish to produce many of these.
I have the need to switch servos between 2 different points, using a simple on/off control signal - but each application (where this will be used to drive a servo) will be different, hence the need to be able to program the 2 different end points in situ, and possibly even define the speed the servo traverses from one to the other (but that's a little bit beyond where I want to get to first).
So the initial program I found looked to have all the answers contained in it, but obviously the first 'setup' part of the program isn't for Picaxe chips, so I was wondering what would need re-configuring for Picaxe, and then I can work on the different subroutines for required functionality.
Hope this helps where I would like to get to,
Cheers for now.
 

Buzby

Senior Member

The original purpose of the code. Easy-peasy with a PICAXE !
 
Hi,

That program is basically just another "dialect" of the BASIC language, so shouldn't be difficult to covert to PICaxe Basic. But without knowing the exact version (which doesn't look to be complete anyway) it will be difficult to convert the exact "numbers" or constants. Also, IMHO the programming looks rather "dumb"; to (need to) store a WORD value into EEPROM for a maximum value of 262 (when a byte can store up to 255) won't be necessary with PICaxe coding. ;)

A starting point is probably to define the pin connections: In the original program "GP0 - 3" are inputs and "GP4 - 5" outputs, but with a PICaxe (08M2), pin C.5 must be the Programming Input and C.0 the Programming Output. Thus, I would map C.0 to the LED (GP4) and the Servo Pulse (GP5) to C.1 (or perhaps C.2 as this is the hardware PWM output of the 08M2). The programming input (C.5) is probably best mapped to "GP1" (if needed) and the other input pins can be allocated in any way convenient for the layout / interconnections.

Then compare the original program with the similar PICaxe commands; in most cases you should find the PICaxe commands are almost the same, but easier to use than the original program. :)

Cheers, Alan.
Hi Alan, thanks for responding.
Good to hear that one program shouldn't be difficult to convert to the other (exactly what I was hoping for!).
Indeed I suspect there will be some tinkering required to find the required 'number/constants' as I'll be using different servos from the original project.
I'll have to get up to speed on the understanding of use of Words, EEPROM and Bytes - would two Bytes be required to store a value of 262, as it exceeds 255? - does PICaxe have a better use of Words, Bytes, EEPROM?

Great to already have some pointers on the required pin changes - I suspected this would be a requirement, and will work on what you have presented.
Also encouraged to hear that PICaxe commands should be similar, and easier to use :)
Cheers for now.
 

AllyCat

Senior Member
Hi,

Yes, in this context a Word consists of two bytes, whilst the instruction set of the "base" PIC works entirely in bytes. Actually, the PICaxe Operating System calculates mainly with Word values, so there is no penalty in working with Word variables (except using them all up), but the memory areas (EEPROM and RAM) are still organised in bytes. PICaxe does have a WORD qualifier for such operations, but IMHO this is an unnecessary complication when the (PICaxe) SERVO command uses less than a full byte, typically values between only 75 and 225 (corresponding to control pulses between 0.75 and 2.25 ms).

Perhaps I was a little unkind to the original Program(mer), because most servos are analogue devices so not intrinsically limited to control by a single byte. But in practice a range of 0 - 255 will be sufficient for most cases, with often a further restriction of hysteresis (or a "dead space") introduced to avoid "dither" or "jitter" in their output position. However, if you do want higher resolution (and the servo, is capable of achieving it) then you can use PULSOUT as a foreground task (in a program loop) rather than the "automatic" (background firmware) control by the dedicated SERVO command.

Cheers, Alan.
 

hippy

Technical Support
Staff member
I have the need to switch servos between 2 different points, using a simple on/off control signal - but each application (where this will be used to drive a servo) will be different, hence the need to be able to program the 2 different end points in situ, and possibly even define the speed the servo traverses from one to the other (but that's a little bit beyond where I want to get to first).
It's often easier to design PICAXE code from scratch rather than try and convert from other code so the definition of what it should do is what is usually most important. So thanks for that detail.

What you want should be fairly easy to do. The following, untested, doesn't include programmability, just uses default settings, but will move from one end to the other at a particular rate depending on which direction a switch is set, will pause for 5 seconds when it reaches either end point before going the other way, once the switch is reversed.
Code:
#Picaxe 08M2
#No_Data

Symbol DIRECTION_IN = pinC.3
Symbol UP           = 1

Symbol SERVO_OUT    = C.2

Symbol minPos       = w1
Symbol maxPos       = w2
Symbol curPos       = w3
Symbol incPos       = w4
Symbol waitTime     = w5
Symbol waiting      = w6
Symbol timing       = w7

PowerOnReset:
  Gosub LoadSettings
  If DIRECTION_IN = UP Then
    curPos = maxPos
  Else
    curPos = minPos
  End If

MainLoop:
  Do
    If waiting > 0 Then
      waiting = waiting Min 20 - 20
    Else
      If DIRECTION_IN = UP Then
        Gosub GoingUp
      Else
        Gosub GoingDown
      End If
    End If
    Gosub UpdateServo
  Loop

GoingUp:
  If curPos < maxPos Then
    curPos = maxPos - incPos Max curPos + incPos
    If curPos = maxPos Then
      waiting = waitTime
    End If
  End If
  Return

GoingDown:
  If curPos > minPos Then
    curPos = minPos + incPos Min curPos - incPos
    If curPos = minPos Then
      waiting = waitTime
    End If
  End If
  Return

UpdateServo:
  timing = curPos / 256
  PulsOut SERVO_OUT, timing
  timing = 2000 - timing
  PauseUs timing
  Return

LoadSettings:
  minPos   =  100 * 256
  maxPos   =  200 * 256
  incPos   =    1 * 256
  waitTime = 5000
  Return
If the switch is moved one way then returned, it will immediately return. If you wanted it to complete the move, pause, before returning that could be implemented.

Adding programmability should be fairly easy but kept that out of the code to avoid complicating how it was.
 
It's often easier to design PICAXE code from scratch rather than try and convert from other code so the definition of what it should do is what is usually most important. So thanks for that detail.

What you want should be fairly easy to do. The following, untested, doesn't include programmability, just uses default settings, but will move from one end to the other at a particular rate depending on which direction a switch is set, will pause for 5 seconds when it reaches either end point before going the other way, once the switch is reversed.
Code:
#Picaxe 08M2
#No_Data

Symbol DIRECTION_IN = pinC.3
Symbol UP           = 1

Symbol SERVO_OUT    = C.2

Symbol minPos       = w1
Symbol maxPos       = w2
Symbol curPos       = w3
Symbol incPos       = w4
Symbol waitTime     = w5
Symbol waiting      = w6
Symbol timing       = w7

PowerOnReset:
  Gosub LoadSettings
  If DIRECTION_IN = UP Then
    curPos = maxPos
  Else
    curPos = minPos
  End If

MainLoop:
  Do
    If waiting > 0 Then
      waiting = waiting Min 20 - 20
    Else
      If DIRECTION_IN = UP Then
        Gosub GoingUp
      Else
        Gosub GoingDown
      End If
    End If
    Gosub UpdateServo
  Loop

GoingUp:
  If curPos < maxPos Then
    curPos = maxPos - incPos Max curPos + incPos
    If curPos = maxPos Then
      waiting = waitTime
    End If
  End If
  Return

GoingDown:
  If curPos > minPos Then
    curPos = minPos + incPos Min curPos - incPos
    If curPos = minPos Then
      waiting = waitTime
    End If
  End If
  Return

UpdateServo:
  timing = curPos / 256
  PulsOut SERVO_OUT, timing
  timing = 2000 - timing
  PauseUs timing
  Return

LoadSettings:
  minPos   =  100 * 256
  maxPos   =  200 * 256
  incPos   =    1 * 256
  waitTime = 5000
  Return
If the switch is moved one way then returned, it will immediately return. If you wanted it to complete the move, pause, before returning that could be implemented.

Adding programmability should be fairly easy but kept that out of the code to avoid complicating how it was.
Hi there,
Thank you for your input and help on this - I've finally got back to it, and have some further thoughts and directions. I'll place a fresh post.
Hopefully you might have some more input?
Thanks in advance.
 
Top