Revision: 1653
Author: [email protected]
Date: Thu Feb  4 00:50:54 2010
Log: new servo.jal
http://code.google.com/p/jallib/source/detail?r=1653

Modified:
 /trunk/include/external/motor/servo/servo.jal
 /trunk/sample/18f452_servo.jal

=======================================
--- /trunk/include/external/motor/servo/servo.jal       Fri Jan 29 00:27:23 2010
+++ /trunk/include/external/motor/servo/servo.jal       Thu Feb  4 00:50:54 2010
@@ -12,11 +12,7 @@
-- http://www.horrorseek.com/home/halloween/wolfstone/Motors/svoint_RCServos.html
 --
 -- usage notes:
--- 1. Set your movement resolution:
---    pulse/movement resolution in increments of 10us (servo_isr speed)
---    lowest possible value is 10
---    low value requires processing power
--- 2. Set your SERVO_MIN values to restrict movement.
+-- 1. Set your SERVO_MIN values to restrict movement.
 --    This step must be completed correctly. First use code as follows
 --    directly after you call servo_init()
 --
@@ -27,7 +23,7 @@
-- Now run your circuit and gradually change SERVO_MIN value so the servo
 --    is at the correct location on one side. Try to get the servo to be
 --    1mm from it's min location.
--- 3. Repeate step 2 with SERVO_MAX but use this:
+-- 2. Repeate step 1 with SERVO_MAX but use this:
 --
 --    servo_move(255,1)
 --    forever loop
@@ -36,161 +32,164 @@
 -- other notes:
 -- This lib uses timer0
-- Up to 8 servos are supported, more servos = more processing power needed. --- you must change SERVO_MIN/SERVO_MAX values each time you change the number
--- of servo's or pulse resolution.
 --
--- here are some examples from my servo:
---
--- SERVO_RESOLUTION = 10
--- SERVO_MIN  - 1 servo 80, 8 servos 190
--- SERVO_MAX  - 1 servo 235, 8 servos 235
---
--- SERVO_RESOLUTION = 20
--- SERVO_MIN  - 1 servo 125
--- SERVO_MAX   - 1 servo 220
---
--- todo:
--- test other clock speeds, prescaler must be changed according to clock speed
---
+
+var byte servo_steps_per_2_5_msec -- holds number of steps within 2.5ms

 -- library variables, internal use only
-var byte _servo_count_1 = 0
-var byte _servo_pulse_1
-var byte _servo_count_2 = 0
-var byte _servo_pulse_2
-var byte _servo_count_3 = 0
-var byte _servo_pulse_3
-var byte _servo_count_4 = 0
-var byte _servo_pulse_4
-var byte _servo_count_5 = 0
-var byte _servo_pulse_5
-var byte _servo_count_6 = 0
-var byte _servo_pulse_6
-var byte _servo_count_7 = 0
-var byte _servo_pulse_7
-var byte _servo_count_8 = 0
-var byte _servo_pulse_8
+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
+var bit servo_3_on at servo_on : 2
+var bit servo_4_on at servo_on : 3
+var bit servo_5_on at servo_on : 4
+var bit servo_6_on at servo_on : 5
+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]

 -- 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_number_count = 0 -- ISR servo control count 0 to 7
+
--------------------------------------------------------------------------------
--- Interupt procedure to pulse servo
+-- Sets servo level high or low. Servo numbers 0 to 7
--------------------------------------------------------------------------------
-procedure _servo_isr() is
-   pragma interrupt
-
-
-   _servo_count_1 = _servo_count_1 + 1        ;increment pulse count
-   if _servo_count_1 <= _servo_pulse_1 then   ;create pulse
-      servo_1 = high
-   elsif _servo_count_1 > _servo_pulse_1 then ;end pluse
-      servo_1 = low
+procedure _servo_set_level(byte in servo_num, bit in level) is
+   pragma inline
+
+   if servo_num == 0 then
+      servo_1 = level
    end if

-   if SERVO_AMOUNT >= 2 then
-      _servo_count_2 = _servo_count_2 + 1        ;increment pulse count
-      if _servo_count_2 <= _servo_pulse_2 then   ;create pulse
-         servo_2 = high
-      elsif _servo_count_2 > _servo_pulse_2 then ;end pluse
-         servo_2 = low
+   if defined(servo_2) == TRUE then
+      if servo_num == 1 & servo_1_on then
+         servo_2 = level
       end if
    end if
-
-   if SERVO_AMOUNT >= 3 then
-      _servo_count_3 = _servo_count_3 + 1        ;increment pulse count
-      if _servo_count_3 <= _servo_pulse_3 then   ;create pulse
-         servo_3 = high
-      elsif _servo_count_3 > _servo_pulse_3 then ;end pluse
-         servo_3 = low
+
+   if defined(servo_3) == TRUE then
+      if servo_num == 2 & servo_2_on then
+         servo_3 = level
       end if
    end if

-   if SERVO_AMOUNT >= 4 then
-      _servo_count_4 = _servo_count_4 + 1        ;increment pulse count
-      if _servo_count_4 <= _servo_pulse_4 then   ;create pulse
-         servo_4 = high
-      elsif _servo_count_4 > _servo_pulse_4 then ;end pluse
-         servo_4 = low
+   if defined(servo_4) == TRUE then
+      if servo_num == 3 & servo_3_on then
+         servo_4 = level
       end if
    end if

-   if SERVO_AMOUNT >= 5 then
-      _servo_count_5 = _servo_count_5 + 1        ;increment pulse count
-      if _servo_count_5 <= _servo_pulse_5 then   ;create pulse
-         servo_5 = high
-      elsif _servo_count_5 > _servo_pulse_5 then ;end pluse
-         servo_5 = low
+   if defined(servo_5) == TRUE then
+      if servo_num == 4 & servo_4_on then
+         servo_5 = level
       end if
    end if

-   if SERVO_AMOUNT >= 6 then
-      _servo_count_6 = _servo_count_6 + 1        ;increment pulse count
-      if _servo_count_6 <= _servo_pulse_6 then   ;create pulse
-         servo_6 = high
-      elsif _servo_count_6 > _servo_pulse_6 then ;end pluse
-         servo_6 = low
+   if defined(servo_6) == TRUE then
+      if servo_num == 5 & servo_5_on then
+         servo_6 = level
       end if
    end if

-   if SERVO_AMOUNT >= 7 then
-      _servo_count_7 = _servo_count_7 + 1        ;increment pulse count
-      if _servo_count_7 <= _servo_pulse_7 then   ;create pulse
-         servo_7 = high
-      elsif _servo_count_7 > _servo_pulse_7 then ;end pluse
-         servo_7 = low
+   if defined(servo_7) == TRUE then
+      if servo_num == 6 & servo_6_on then
+         servo_7 = level
       end if
    end if

-   if SERVO_AMOUNT >= 8 then
-      _servo_count_8 = _servo_count_8 + 1        ;increment pulse count
-      if _servo_count_8 <= _servo_pulse_8 then   ;create pulse
-         servo_8 = high
-      elsif _servo_count_8 > _servo_pulse_8 then ;end pluse
-         servo_8 = low
+   if defined(servo_8) == TRUE then
+      if servo_num == 7 & servo_7_on then
+         servo_8 = level
       end if
    end if

-   if INTCON_TMR0IF == true then
-      tmr0 = (255 - (SERVO_RESOLUTION / 10)) + 1           ;set timing
-      INTCON_TMR0IF = off  ;reset counter
-   end if
-
+end procedure
+
+--------------------------------------------------------------------------------
+-- Interupt procedure to pulse servo
+--------------------------------------------------------------------------------
+
+procedure _servo_isr() is
+   pragma interrupt
+
+   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
+      end if
+      _servo_isr_count = 0                           -- go to first step
+   end if
 end procedure

--------------------------------------------------------------------------------
 -- Move a servo to any value from 0 to 255
--------------------------------------------------------------------------------
 procedure servo_move(word in value, byte in servo_number) is
-   var word calc1, calc2
-   var word final
+   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
    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
+      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_1 = (255 - final2) -- move servo 1 by pulse length
+     _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_2 = (255 - final2) -- move servo 2 by pulse length
+     _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_3 = (255 - final2) -- move servo 2 by pulse length
+     _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_4 = (255 - final2) -- move servo 2 by pulse length
+     _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_5 = (255 - final2) -- move servo 2 by pulse length
+     _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_6 = (255 - final2) -- move servo 2 by pulse length
+     _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_7 = (255 - final2) -- move servo 2 by pulse length
+     _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_8 = (255 - final2) -- move servo 2 by pulse length
+     _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)
   end if
 end procedure

@@ -198,13 +197,58 @@
 -- Initialize  the servo
--------------------------------------------------------------------------------
 procedure servo_init() is
-   OPTION_REG_PS = 4 ; prescaler
-
+   -- 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
+   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
+      forever loop
+         if servo_steps > 255 then
+            servo_prescaler = servo_prescaler + 1
+            servo_steps = servo_steps / 2
+         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
+      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
+   end if
 end procedure
=======================================
--- /trunk/sample/18f452_servo.jal      Fri Jan 29 00:27:23 2010
+++ /trunk/sample/18f452_servo.jal      Thu Feb  4 00:50:54 2010
@@ -13,7 +13,7 @@
-- http://www.horrorseek.com/home/halloween/wolfstone/Motors/svoint_RCServos.html
 --
 -- notes:
--- see notes in library file servo.jal
+-- see usage notes in library file servo.jal, very important!
 --

 -- include chip
@@ -50,64 +50,79 @@
 alias servo_2_direction   is pin_b1_direction
 servo_2_direction = output
 --
-;alias servo_3             is pin_b2
-;alias servo_3_direction   is pin_b2_direction
-;servo_3_direction = output
-;--
-;alias servo_4             is pin_b3
-;alias servo_4_direction   is pin_b3_direction
-;servo_4_direction = output
-;--
-;alias servo_5             is pin_b4
-;alias servo_5_direction   is pin_b4_direction
-;servo_5_direction = output
-;--
-;alias servo_6             is pin_b5
-;alias servo_6_direction   is pin_b5_direction
-;servo_6_direction = output
-;--
-;alias servo_7             is pin_b6
-;alias servo_7_direction   is pin_b6_direction
-;servo_7_direction = output
-;--
-;alias servo_8             is pin_b7
-;alias servo_8_direction   is pin_b7_direction
-;servo_8_direction = output
-
--- set number of servos
-const byte SERVO_AMOUNT = 2
--- set movement resolution
-const byte SERVO_RESOLUTION = 10
--- with resolution = 10
-const byte SERVO_MIN   = 80
-const byte SERVO_MAX   = 235
+alias servo_3             is pin_b2
+alias servo_3_direction   is pin_b2_direction
+servo_3_direction = output
 --
+alias servo_4             is pin_b3
+alias servo_4_direction   is pin_b3_direction
+servo_4_direction = output
+--
+alias servo_5             is pin_b4
+alias servo_5_direction   is pin_b4_direction
+servo_5_direction = output
+--
+alias servo_6             is pin_b5
+alias servo_6_direction   is pin_b5_direction
+servo_6_direction = output
+--
+alias servo_7             is pin_b6
+alias servo_7_direction   is pin_b6_direction
+servo_7_direction = output
+--
+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
 include servo -- include the servo library
 servo_init()

-servo_move(127,1) ;start servo 1 centered
-servo_move(127,2) ;start servo 2 centered
-
--- move both servo's in opposite directions
+-- use this to turn off a servo
+;servo_1_on = False
+
+-- example center all servo's
+servo_move(127,1)
+servo_move(127,2)
+servo_move(127,3)
+servo_move(127,4)
+servo_move(127,5)
+servo_move(127,6)
+servo_move(127,7)
+servo_move(127,8)
+
+-- stop here (good for measurements)
+;forever loop
+;end loop
+
+-- example moving servos one and two and blink led
 forever loop
+
+   servo_move(255,1)
+   servo_move(0,2)
+   _usec_delay (1_000_000)
    led = !led
-   _usec_delay(500_000)
-   servo_move(0,1)          ;move all the way to one side
-   servo_move(256,2)
-
+
+   servo_move(127,1) ;servo 1 centered
+   servo_move(127,2) ;servo 2 centered
+   _usec_delay (1_000_000)
    led = !led
-   _usec_delay(500_000)
-   servo_move(127,1)        ;move to center
-   servo_move(127,2)
-
+
+   servo_move(0,1)
+   servo_move(255,2)
+   _usec_delay (1_000_000)
    led = !led
-   _usec_delay(500_000)
-   servo_move(256,1)        ;move all the way to the other side
-   servo_move(0,2)
-
+
+   servo_move(127,1) ;servo 1 centered
+   servo_move(127,2) ;servo 2 centered
+   _usec_delay (1_000_000)
    led = !led
-   _usec_delay(500_000)
-   servo_move(127,1)        ;move to center
-   servo_move(127,2)
 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.

Reply via email to