Welcome, Guest
Username: Password: Secret Key Remember me

TOPIC: Swordfish Module - Servo.bas

Re: Swordfish Module - Servo.bas 9 years 7 months ago #15287



Full credit is given to MichealM, whose method of controlling servos - posted here - forms the basis of this module.



This module controls between 1 and 8 hobby servos connected to PortB.  The module will only affect the pins which have servos connected - if less than 8 servos are used then the remaining pins on PortB can be used for other I/O.

Please Note: The module will only work correctly if the PIC is clocked at 4, 8, 16, or 32MHz


Using the Module


The module's options and their default values are:

#option Servo_NumberOfServos = 8                    'Number of servos (1 - 8)
#option Servo_Priority = ipHigh                     'Servo interrupt priority

Servo_NumberOfServos sets the number of servos which will be controlled. Valid values are 1 to 8.

Servo_Priority sets whether the module's interrupt will be run as high or low priority. For best results, this should be left as high priority.


Connecting servos

Servo 0 should be connected to PortB.0; Servo 1 connected to PortB.1; and so on.


Setting Servo Positions

Servos are controlled by sending them a pulse of between 600uS and 2400uS duration every 20mS. The length of the pulse determines the servo's position, with 1500uS being approximately halfway.

The module stores the position of each servo in the word array ServoPosition. To set a particular servo's position, load the length of the desired pulse (in uS) into the array. i.e. to set Servo 3 to the maximum position, use ServoPosition(3) = 2400




Calling this routine will enable the interrupt and start sending pulses to the servos.


Calling this routine stops the interrupt from firing and stops sending pulses to the servos. Note: If they are not receiving control pulses then servos will only hold their current position if no force is acting on them. However, turning off the interrupt may be useful if you need to execute a piece of code which must not be interrupted.


Example Program

This example program controls 3 servos.  Servo 0 is controlled by an analog input on AN0 while Servos 1 & 2 constantly move through their full range of motion.

Device = 18F2520
Clock = 4
#option Servo_NumberOfServos = 3
Include "Servo.bas"
Dim Counter As Word
Function GetVoltage() As Byte
'Returns byte value representing voltage on AN0 pin (0 = 0V, 255 = 5V)
    ADCON0.0 = 1                        'Turn on A/D module
    ADCON0.5 = 0                        '}
    ADCON0.4 = 0                        '}Set A/D channel to AN0
    ADCON0.3 = 0                        '}
    ADCON0.2 = 0                        '}
    ADCON0.1 = 1                        'Start conversion
    While ADCON0.1 = 1                  '}Wait for conversion to finish
    Wend                                '}
    Result = ADRESH                     'Store result (8 MSBs only)
    ADCON0.0 = 0                        'Turn off A/D module
End Function
'Main Program
'---Set-up analog to digital converter
ADCON1.5 = 0                            '}Set A/D Vref+ and Vref- to Vdd and Vss
ADCON1.4 = 0                            '}
ADCON1.3 = 1                            '}
ADCON1.2 = 1                            '}AN0 set to analog input
ADCON1.1 = 1                            '}
ADCON1.0 = 0                            '}
ADCON2.7 = 0                            'A/D result left justified
ADCON2.5 = 1                            '}
ADCON2.4 = 0                            '}Set A/D Aquisition time to 12 Tad
ADCON2.3 = 1                            '}
ADCON2.2 = 0                            '}Set A/D Converstion Clock to Fosc / 8
ADCON2.1 = 0                            '}This is the minimum possible with a
ADCON2.0 = 1                            '}clock speed of 4MHz (Tad = 2uS)
Servo.On                                'Start sending servo control pulses
While True
    For Counter = 600 To 2400
        Servo.ServoPosition(0) = GetVoltage * 7 + 600
        Servo.ServoPosition(1) = Counter
        Servo.ServoPosition(2) = 3000 - Counter
    For Counter = 2400 To 600 Step -1
        Servo.ServoPosition(0) = GetVoltage * 7 + 600
        Servo.ServoPosition(1) = Counter
        Servo.ServoPosition(2) = 3000 - Counter




This Boolean variable is set to "True" when the interrupt has finished executing. The interrupt is only called at the end of each servo pulse. Therefore, if you have a piece of code which must not be interrupted then you can do something like this:

Servo.ServoInterruptComplete = False
Repeat					'}Wait for the interrupt to complete
Until Servo.ServoInterruptComplete = True	'}
'Do important bit of code


Once the flag is set to True, you know you have at least 600us (minimum servo pulse duration) to execute code before the interrupt will trigger again.
Read full article...
Time to create page: 0.250 seconds