Revision: 1669
Author: [email protected]
Date: Tue Feb 16 22:23:44 2010
Log: servo lib now supports timer0, timer1 or timer3
http://code.google.com/p/jallib/source/detail?r=1669
Modified:
/trunk/include/external/motor/servo/servo.jal
/trunk/sample/18f452_servo.jal
=======================================
--- /trunk/include/external/motor/servo/servo.jal Thu Feb 4 21:10:09 2010
+++ /trunk/include/external/motor/servo/servo.jal Tue Feb 16 22:23:44 2010
@@ -30,13 +30,22 @@
-- end loop
--
-- other notes:
--- This lib uses timer0
--- Up to 8 servos are supported, more servos = more processing power
needed.
+-- This lib uses timer0, timer1 or timer3
+-- Up to 8 servos are supported
--
-var byte servo_steps_per_2_5_msec -- holds number of steps within 2.5ms
-
--- library variables, internal use only
+-- you may modify servo_steps_per_2_5_msec directly for more exact
movements
+if SERVO_USE_TIMER == 0 then
+ var byte servo_steps_per_2_5_msec -- holds number of steps within 2.5ms
+ var byte _servo_pulse[8]
+ var byte _servo_low[8]
+else
+ var word servo_steps_per_2_5_msec -- holds number of steps within 2.5ms
+ var word _servo_pulse[8]
+ var word _servo_low[8]
+end if
+
+-- use these variables to turn servo's on or off
var byte servo_on = 0xFF -- All servo's on by default
var bit servo_1_on at servo_on : 0
var bit servo_2_on at servo_on : 1
@@ -47,63 +56,99 @@
var bit servo_7_on at servo_on : 6
var bit servo_8_on at servo_on : 7
-var byte _servo_pulse[8]
-var byte _servo_low[8]
+-- setup the timer aliases for the timer the user selected
+if SERVO_USE_TIMER == 0 then
+ -- set special timer0 settings
+ t0con_psa = 0 -- assign prescaler to timer0
+ -- aliases timer0 for 18f PICs
+ if target_cpu == PIC_16 then
+ alias option_reg_t0cs is t0con_t0cs
+ alias option_reg_psa is t0con_psa
+ alias option_reg_ps is t0con_t0ps
+ end if
+ -- set timer registers to timer0
+ alias servo_tmr is tmr0 -- timer interval
+ alias servo_cs is t0con_t0cs -- timer clock source bit
+ alias servo_ie is intcon_tmr0ie -- interupt enable
+ alias servo_if is intcon_tmr0if -- interupt overflow bit
+ alias servo_ps is t0con_t0ps -- timer prescaler select bits
+elsif SERVO_USE_TIMER == 1 then
+ -- set special timer1 settings
+ t1con_tmr1on = 1 -- enables timer 1
+ -- set timer registers to timer1
+ alias servo_tmr is tmr1 -- timer interval
+ alias servo_cs is T1CON_TMR1CS -- timer clock source bit
+ alias servo_ie is PIE1_TMR1IE -- interupt enable
+ alias servo_if is PIR1_TMR1IF -- interupt overflow bit
+ alias servo_ps is T1CON_T1CKPS -- timer prescaler select bits
+elsif SERVO_USE_TIMER == 2 then
+ -- set special timer2 settings
+ pragma error -- timer2 is not supported
+elsif SERVO_USE_TIMER == 3 then
+ t3con_tmr3on = 1 -- enables timer 3
+ -- set timer registers to timer3
+ alias servo_tmr is tmr3 -- timer interval
+ alias servo_cs is T3CON_TMR3CS -- timer clock source bit
+ alias servo_ie is PIE2_TMR3IE -- interupt enable
+ alias servo_if is PIR2_TMR3IF -- interupt overflow bit
+ alias servo_ps is T3CON_T3CKPS -- timer prescaler select bits
+end if
-- calculate difference between min & max
const byte _SERVO_CALC_DIFF = SERVO_MAX - SERVO_MIN
-var byte _servo_isr_count = 0 -- ISR steps (high level, low level)
+var byte _servo_isr_count = 0 -- ISR step count (0 - servo pulse / 1 -
idle state)
var byte _servo_number_count = 0 -- ISR servo control count 0 to 7
--------------------------------------------------------------------------------
-- Sets servo level high or low. Servo numbers 0 to 7
+-- only set level if servo_x_on = true
--------------------------------------------------------------------------------
procedure _servo_set_level(byte in servo_num, bit in level) is
pragma inline
- if servo_num == 0 then
+ if servo_num == 1 & servo_1_on then
servo_1 = level
end if
-
+
if defined(servo_2) == TRUE then
- if servo_num == 1 & servo_1_on then
+ if servo_num == 1 & servo_2_on then
servo_2 = level
end if
end if
if defined(servo_3) == TRUE then
- if servo_num == 2 & servo_2_on then
+ if servo_num == 2 & servo_3_on then
servo_3 = level
end if
end if
if defined(servo_4) == TRUE then
- if servo_num == 3 & servo_3_on then
+ if servo_num == 3 & servo_4_on then
servo_4 = level
end if
end if
if defined(servo_5) == TRUE then
- if servo_num == 4 & servo_4_on then
+ if servo_num == 4 & servo_5_on then
servo_5 = level
end if
end if
if defined(servo_6) == TRUE then
- if servo_num == 5 & servo_5_on then
+ if servo_num == 5 & servo_6_on then
servo_6 = level
end if
end if
if defined(servo_7) == TRUE then
- if servo_num == 6 & servo_6_on then
+ if servo_num == 6 & servo_7_on then
servo_7 = level
end if
end if
if defined(servo_8) == TRUE then
- if servo_num == 7 & servo_7_on then
+ if servo_num == 7 & servo_8_on then
servo_8 = level
end if
end if
@@ -117,83 +162,77 @@
procedure _servo_isr() is
pragma interrupt
- if ! INTCON_TMR0IF then -- Exit if it is not a timer0 interupt
- return
- end if
-
- if _servo_isr_count == 0 then -- do pulse high width
- INTCON_TMR0IF = off -- reset counter
- tmr0 = _servo_pulse[_servo_number_count] -- set timer to pulse
high width
- _servo_set_level (_servo_number_count,HIGH) -- set level to high
- _servo_isr_count = _servo_isr_count + 1 -- go to next step
- elsif _servo_isr_count == 1 then -- finnish pulse low
- INTCON_TMR0IF = off -- reset counter
- tmr0 = _servo_low[_servo_number_count]
- _servo_set_level (_servo_number_count,LOW) -- set level to low
- _servo_isr_count = _servo_isr_count + 1 -- go to next step
- _servo_number_count = _servo_number_count + 1 -- change to next
servo
- if _servo_number_count == 8 then -- change to first
servo if needed
- _servo_number_count = 0
+ if servo_if then -- check if it is a timer interupt
+ if _servo_isr_count == 0 then -- do the servo
pulse (high)
+ servo_if = off -- reset counter
+ servo_tmr = _servo_pulse[_servo_number_count] -- set timer to
pulse high width
+ _servo_set_level (_servo_number_count,HIGH) -- set level to
high
+ _servo_isr_count = _servo_isr_count + 1 -- go to next step
+ elsif _servo_isr_count == 1 then -- do the servo
idle state (low)
+ servo_if = off -- reset counter
+ servo_tmr = _servo_low[_servo_number_count] -- set timer to
pulse low width
+ _servo_set_level (_servo_number_count,LOW) -- set level to low
+ _servo_isr_count = _servo_isr_count + 1 -- go to next step
+ _servo_number_count = _servo_number_count + 1 -- change to next
servo
+ if _servo_number_count == 8 then -- change to first
servo if needed
+ _servo_number_count = 0 -- go back to
first servo
+ end if
+ _servo_isr_count = 0 -- go to first step
end if
- _servo_isr_count = 0 -- go to first step
end if
end procedure
--------------------------------------------------------------------------------
--- Move a servo to any value from 0 to 255
+-- Move a servo to any location from 0 to 255
--------------------------------------------------------------------------------
-procedure servo_move(word in value, byte in servo_number) is
+procedure servo_move(byte in location, byte in servo_number) is
var dword calc1, calc2
var dword final
- var byte final2
-
- ;calculate the pulse length
- calc1 = (value * _SERVO_CALC_DIFF)
- ;calc2 = calc1 / servo_steps_per_2_5_msec
+ var word location2 = location -- change location to word for overflow
+
+ -- map input location to 0-255 according to servo_min/servo_max
+ calc1 = (location2 * _SERVO_CALC_DIFF)
calc2 = calc1 / 255
final = calc2 + servo_min
-
- -- change final into a byte
- var byte val[2] at final
- final2 = val[0]
-
- if SERVO_CLOCK_BITS == 8 then
- ;calculate the pulse length
+
+ if SERVO_USE_TIMER == 0 then -- if 8 bit timer 0
+ var byte final2
+
+ -- change final into a byte
+ var byte val[1] at final
+ final2 = val[0]
+
+ ;calculate the pulse length
calc1 = (final2 * servo_steps_per_2_5_msec)
- ;calc2 = calc1 / servo_steps_per_2_5_msec
final = calc1 / 255
- -- change final into a byte
- var byte val2[2] at final
- final2 = val2[0]
- else
- pragma error -- 16 bit timers are not supported yet
- end if
-
- if servo_number == 1 then
- _servo_pulse[0] = (255 - final2) -- move servo 1 by pulse length
- _servo_low[0] = (255 - _servo_pulse[0]) + (255 -
servo_steps_per_2_5_msec)
- elsif servo_number == 2 then
- _servo_pulse[1] = (255 - final2) -- move servo 2 by pulse length
- _servo_low[1] = (255 - _servo_pulse[1]) + (255 -
servo_steps_per_2_5_msec)
- elsif servo_number == 3 then
- _servo_pulse[2] = (255 - final2) -- move servo 2 by pulse length
- _servo_low[2] = (255 - _servo_pulse[2]) + (255 -
servo_steps_per_2_5_msec)
- elsif servo_number == 4 then
- _servo_pulse[3] = (255 - final2) -- move servo 2 by pulse length
- _servo_low[3] = (255 - _servo_pulse[3]) + (255 -
servo_steps_per_2_5_msec)
- elsif servo_number == 5 then
- _servo_pulse[4] = (255 - final2) -- move servo 2 by pulse length
- _servo_low[4] = (255 - _servo_pulse[4]) + (255 -
servo_steps_per_2_5_msec)
- elsif servo_number == 6 then
- _servo_pulse[5] = (255 - final2) -- move servo 2 by pulse length
- _servo_low[5] = (255 - _servo_pulse[5]) + (255 -
servo_steps_per_2_5_msec)
- elsif servo_number == 7 then
- _servo_pulse[6] = (255 - final2) -- move servo 2 by pulse length
- _servo_low[6] = (255 - _servo_pulse[6]) + (255 -
servo_steps_per_2_5_msec)
- elsif servo_number == 8 then
- _servo_pulse[7] = (255 - final2) -- move servo 2 by pulse length
- _servo_low[7] = (255 - _servo_pulse[7]) + (255 -
servo_steps_per_2_5_msec)
+ -- change final into a byte
+ var byte val2[2] at final
+ final2 = val2[0]
+
+ -- set the timer value
+ _servo_pulse[servo_number - 1] = (255 - final2) -- move servo 1 by
pulse length
+ _servo_low[servo_number - 1] = (255 - _servo_pulse[servo_number - 1])
+ (255 - servo_steps_per_2_5_msec)
+ else -- if 16 bit timer1 or timer3
+ var dword final2
+ var word final3
+
+ -- change final into a word
+ var byte val[2] at final
+ final2 = (val[1] << 8) + val[0]
+
+ ;calculate the pulse length
+ calc1 = (final2 * servo_steps_per_2_5_msec)
+ final = calc1 / 255
+
+ -- change final into a word
+ var byte val2[2] at final
+ final3 = val2[1]
+ final3 = (final3 <<8) + val2[0]
+
+ -- set the timer value
+ _servo_pulse[servo_number - 1] = (65535 - final3) -- move servo 1 by
pulse length
+ _servo_low[servo_number - 1] = (65535 - _servo_pulse[servo_number -
1]) + (65535 - servo_steps_per_2_5_msec)
end if
end procedure
@@ -201,58 +240,67 @@
-- Initialize the servo
--------------------------------------------------------------------------------
procedure servo_init() is
- -- prescaler value - measured timer step widths on 20mhz
- -- 6 - 25.6 us
- -- 5 - 12.8 us
- -- 4 - 6.4 us
- -- 3 - 3.2 us
- -- 2 - 1.6 us
- -- 1 - 0.8 us
-
- OPTION_REG_T0CS = 0 ; internal clock
- OPTION_REG_PSA = 0 ; assign prescaler to timer0
-
- INTCON_TMR0IF = off ; start the setting
- INTCON_TMR0IE = on
- INTCON_GIE = on ; enable global interrupts
- INTCON_PEIE = on
-
- -- calculate number of steps available within 2.5ms
-
- -- On 20mhz clock, this is the measured timer step
- -- size (8us), then do 1/8us = 125000
- const dword SERVO_TIMER_DIFF = 125000
- --
- const dword SERVO_CALC_1 = target_clock * 100 --
lower number
- const dword SERVO_CALC_2 = SERVO_CALC_1 / 20_000_000 -- compaire to
20mhz
- const dword SERVO_CALC_3 = SERVO_CALC_2 * SERVO_TIMER_DIFF
- const dword SERVO_CALC_4 = SERVO_CALC_3 / 100 -- higher
number
- const dword SERVO_STEP_US_X_1000 = 1_000_000_000 / SERVO_CALC_4
- --
- var dword servo_steps = 25000000 / SERVO_STEP_US_X_1000
-
- -- change prescaler if using 8-bit timer
- var byte servo_prescaler = 1
- if SERVO_CLOCK_BITS == 8 then
+ -- enable global interupts
+ INTCON_GIE = on -- Enables all unmasked interrupts
+ INTCON_PEIE = on -- Enables all unmasked peripheral interrupts
+
+ servo_if = off -- clear interupt overflow bit
+ servo_ie = on -- timer overflow interupt enable
+ servo_cs = 0 -- use internal clock for timer
+
+ if SERVO_USE_TIMER == 0 then
+ -- timer0 min step time of (1/osc)*16. (0.8us at 20mhz)
+
+ -- calculate number of steps available within 2.5ms ;example on 20mhz
+ const dword SERVO_CALC_1 = target_clock / 10_000 ;= 2000
+ const dword SERVO_CALC_2 = SERVO_CALC_1 / 4 ;= 500
+ const dword SERVO_CALC_3 = 10_000 / SERVO_CALC_2 ;= 20
+ const dword SERVO_CALC_4 = SERVO_CALC_3 * 4 ;= 80
+ var dword servo_steps = 250_000 / SERVO_CALC_4 ;= 3125
+
+ -- increase prescaler if 256 clock pulses is not enouf time
+ var byte servo_prescaler = 1
forever loop
if servo_steps > 255 then
- servo_prescaler = servo_prescaler + 1
- servo_steps = servo_steps / 2
+ servo_prescaler = servo_prescaler + 1 -- increase prescaller
+ servo_steps = servo_steps / 2 -- decrease timer steps
needed
else
exit loop
end if
end loop
- else
- pragma error -- 16 bit timers are not supported yet
- end if
-
- option_reg_ps = servo_prescaler
- -- servo_steps is now calculated
-
- if SERVO_CLOCK_BITS == 8 then
+
+ -- servo_steps is now calculated, set the prescaller
+ servo_ps = servo_prescaler
+
+ -- put it into a byte for the 8 bit timer
var byte value[1] at servo_steps
servo_steps_per_2_5_msec = value[0]
else
- pragma error -- 16 bit timers are not supported yet
+ -- timer1 & timer3 min step time is (1/osc)*4. (0.2us at 20mhz)
+
+ -- calculate number of steps available within 2.5ms ;example on 20mhz
+ const dword SERVO_CALC_1 = target_clock / 10_000 ;= 2000
+ const dword SERVO_CALC_2 = 10_000 / SERVO_CALC_1 ;= 20
+ const dword SERVO_CALC_3 = SERVO_CALC_2 * 4 ;= 80
+ var dword servo_steps = 250_000 / SERVO_CALC_3 ;= 3125
+
+ -- increase prescaler if 65535 clock pulses is not enouf time
+ var byte servo_prescaler = 0
+ forever loop
+ if servo_steps > 65535 then
+ servo_prescaler = servo_prescaler + 1 -- increase prescaller
+ servo_steps = servo_steps / 2 -- decrease timer steps
needed
+ else
+ exit loop
+ end if
+ end loop
+
+ -- servo_steps is now calculated, set the prescaller
+ servo_ps = servo_prescaler
+
+ -- put it into a word for the 16 bit timer
+ var word value[2] at servo_steps
+ servo_steps_per_2_5_msec = (value[1] << 8) + value[0] ; equals 12500
on 20mhz
+
end if
end procedure
=======================================
--- /trunk/sample/18f452_servo.jal Thu Feb 4 00:50:54 2010
+++ /trunk/sample/18f452_servo.jal Tue Feb 16 22:23:44 2010
@@ -16,11 +16,11 @@
-- see usage notes in library file servo.jal, very important!
--
--- include chip
-include 18F452 -- target picmicro
-
+include 18f452 -- target PICmicro
+--
-- This program assumes a 20 MHz resonator or crystal
-- is connected to pins OSC1 and OSC2.
+-- Unspecified configuration bits may cause a different frequency!
pragma target clock 20_000_000 -- oscillator frequency
-- configuration memory settings (fuses)
pragma target OSC HS -- HS crystal or resonator
@@ -29,18 +29,11 @@
enable_digital_io() -- disable analog I/O (if any)
--- led definition
-alias led is pin_a0
-alias led_direction is pin_a0_direction
---
+-- LED IO definition
+alias led is pin_a0
+alias led_direction is pin_a0_direction
led_direction = output
--- aliases timer0 for 18f PICs (remove if you are using 16f)
--- timer0 is used by servo.jal
-alias option_reg_t0cs is t0con_t0cs
-alias option_reg_psa is t0con_psa
-alias option_reg_ps IS t0con_t0ps
-
-- setup servo pins
alias servo_1 is pin_b0
alias servo_1_direction is pin_b0_direction
@@ -73,19 +66,16 @@
alias servo_8 is pin_b7
alias servo_8_direction is pin_b7_direction
servo_8_direction = output
-
+--
-- choose min & max servo movment / pulse size
const byte SERVO_MIN = 50 -- default is 50 (0.5ms min pulse)
const byte SERVO_MAX = 255 -- default is 255 (2.5ms max pulse)
-
--- servo lib currently only supports timer 0, an 8 bit clock
-const byte SERVO_CLOCK_BITS = 8
+--
+const byte SERVO_USE_TIMER = 3 -- use PICs internal timer (0, 1 or 3)
+--
include servo -- include the servo library
servo_init()
--- use this to turn off a servo
-;servo_1_on = False
-
-- example center all servo's
servo_move(127,1)
servo_move(127,2)
@@ -96,30 +86,28 @@
servo_move(127,7)
servo_move(127,8)
--- stop here (good for measurements)
-;forever loop
-;end loop
+-- use this to turn off a servo
+;servo_1_on = False
-- example moving servos one and two and blink led
forever loop
-
- servo_move(255,1)
- servo_move(0,2)
+ servo_move(255,1) -- servo 1 right
+ servo_move(0,2) -- servo 2 left
_usec_delay (1_000_000)
led = !led
- servo_move(127,1) ;servo 1 centered
- servo_move(127,2) ;servo 2 centered
+ servo_move(127,1) -- servo 1 centered
+ servo_move(127,2) -- servo 2 centered
_usec_delay (1_000_000)
led = !led
- servo_move(0,1)
- servo_move(255,2)
+ servo_move(0,1) -- servo 1 left
+ servo_move(255,2) -- servo 2 right
_usec_delay (1_000_000)
led = !led
- servo_move(127,1) ;servo 1 centered
- servo_move(127,2) ;servo 2 centered
+ servo_move(127,1) -- servo 1 centered
+ servo_move(127,2) -- servo 2 centered
_usec_delay (1_000_000)
led = !led
end loop
--
You received this message because you are subscribed to the Google Groups
"jallib" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/jallib?hl=en.