In SX Microcontrollers, SX/B Compiler and SX-Key Tool, JonnyMac wrote: In the prop industry servos are frequently used for animatronics and special FX. Since we're (EFX-TEK) about to release a Prop-SX controller, I thought it would be fun to write a little framework program that allows our customers to control servos as easily as their digital outputs. What I did, in effect, was make a little servo controller VP. The code is pretty easy, and entirely in SX/B. By using the VP approach one can simply write a position value to a servo and the interrupt code will take care of the refreshing. The only restriction is that you can't use things like PAUSE, SERIN, etc. -- those functions that are timing-dependant. Since timing is a big part of prop control this framework includes subroutines that use an interrupt-driven timer for delays. [code] ' ========================================================================= ' ' File...... Prop484-EZ.SXB ' Purpose... Prop Control framework: 4 triggers, 8 outs, 4 servos ' Author.... Jon Williams, EFX-TEK ' Copyright (c) 2007 EFX-TEK ' Some Rights Reserved ' -- see http://creativecommons.org/licenses/by/2.5/ ' E-mail.... jwilliams@efx-tek.com ' Started... ' Updated... 06 FEB 2007 ' ' ========================================================================= ' ------------------------------------------------------------------------- ' Program Description ' ------------------------------------------------------------------------- ' ' This program provides a framework for simple prop control that may use ' multiple trigger inputs, digital outputs, as well as servos. ' ' An ISR (Interrupt Servo Routine) is used to process the servos so that ' the user needs only set the current position (in the pos(x) array) -- no ' updating or delays are required (as with the Prop-1 or Prop-2). ' ' Note: SERIN, SEROUT, PAUSE, PAUSEUS cannot be used with this framework. ' Use the WAIT_x subroutines for program delays. ' ------------------------------------------------------------------------- ' Conditional Compilation Symbols ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- DEVICE SX28, OSCXT2, TURBO, STACKX, OPTIONX, BOR42 FREQ 20_000_000 ID "P448-EZ" ' ------------------------------------------------------------------------- ' IO Pins ' ------------------------------------------------------------------------- Trigger3 PIN RC.7 ' inputs Trigger2 PIN RC.6 Trigter1 PIN RC.5 Trigger0 PIN RC.4 ServoCtrl PIN RC Servo3 PIN RC.3 OUTPUT ' servo outputs Servo2 PIN RC.2 OUTPUT Servo1 PIN RC.1 OUTPUT Servo0 PIN RC.0 OUTPUT Outs PIN RB OUTPUT ' digital outputs Out7 PIN RB.7 Out6 PIN RB.6 Out5 PIN RB.5 Out4 PIN RB.4 Out3 PIN RB.3 Out2 PIN RB.2 Out1 PIN RB.1 Out0 PIN RB.0 ' ------------------------------------------------------------------------- ' Constants ' ------------------------------------------------------------------------- IsOn CON 1 IsOff CON 0 ' ------------------------------------------------------------------------- ' Variables ' ------------------------------------------------------------------------- flags VAR Byte sync VAR flags.0 ' marks start of frame idx VAR Byte tix VAR Word ' (ISR) timer svoPos VAR Byte (4) ' servo positions svoFrame VAR Word ' (ISR) servo frame timer svoIdx VAR Byte ' (ISR) active servo index svoPin VAR Byte ' (ISR) mask for active servo svoTimer VAR Byte ' (ISR) servo pulse timer tmpB1 VAR Byte ' for subs/funcs tmpB2 VAR Byte tmpW1 VAR Word ' ------------------------------------------------------------------------- INTERRUPT 100_000 ' run every 10 uS ' ------------------------------------------------------------------------- ' The ISR code is setup to run every 10 uS so that the pos(x) values match ' the BS1 PULSOUT parameter for servo control (100 to 200); this simplifies ' the code and uses less variable space. Only one servo pulse is on at a ' given time. ' ' Note that after Servo3 is done the ISR waits until the start of the next ' 20 mS frame to start Servo0. Update_Timer: IF tix > 0 THEN ' update delay timer if on DEC tix ENDIF Check_Frame_Timer: IF svoFrame = 0 THEN ' time for new servo frame? svoFrame = 2000 ' reload with 20 ms svoPin = %0001 ' start servo cycle svoIdx = 0 ' set position pointer svoTimer = svoPos(0) ' load position timing sync = IsOn ' mark start of frame GOTO Refesh_Servo_Outs ELSE DEC svoFrame ' no, update running timer sync = IsOff ' clear sync marker ENDIF Check_Servo_Timer: IF svoPin = 0 THEN ISR_Exit ' abort if none running DEC svoTimer IF svoTimer > 0 THEN ISR_Exit ' abort if servo still running Reload_Servo_Timer: INC svoIdx ' point to next servo svoIdx.2 = 0 ' keep 0 - 3 svoTimer = svoPos(svoIdx) ' load position timing Select_Next_Servo: svoPin = svoPin << 1 svoPin = svoPin & $0F ' limit to four servos Refesh_Servo_Outs: ServoCtrl = ServoCtrl & $F0 ' clear last servo ServoCtrl = ServoCtrl | svoPin ' set active servo ISR_Exit: RETURNINT ' ========================================================================= PROGRAM Start ' ========================================================================= ' ------------------------------------------------------------------------- ' Subroutine Declarations ' ------------------------------------------------------------------------- WAIT_TIX SUB 1, 2 ' wait in 10 us units WAIT_MS SUB 1, 2 ' wait in 1 ms units WAIT_SYNC SUB 0 ' wait for frame ' ------------------------------------------------------------------------- ' Program Code ' ------------------------------------------------------------------------- Start: FOR idx = 0 TO 3 svoPos(idx) = 150 ' start at center NEXT Main: FOR idx = 100 TO 200 svoPos(0) = idx WAIT_MS 60 ' slow sweep NEXT GOTO Main ' ------------------------------------------------------------------------- ' Subroutine Code ' ------------------------------------------------------------------------- '' Use: WAIT_MS ticks ' -- hold program in 10 uS ticks (1 to 65535) WAIT_TIX: IF __PARAMCNT = 1 THEN tix = __PARAM1 ' get byte value ELSE tix = __WPARAM12 ' get word value ENDIF DO WHILE tix > 0 ' hold while running LOOP RETURN ' ------------------------------------------------------------------------- ' Use: WAIT_MS mSecs ' -- hold program in milliseconds (1 to 65535) WAIT_MS: IF __PARAMCNT = 1 THEN tmpW1 = __PARAM1 ' get byte value ELSE tmpW1 = __WPARAM12 ' get word value ENDIF DO WHILE tmpW1 > 0 tix = 100 DO WHILE tix > 0 LOOP DEC tmpW1 LOOP RETURN ' ------------------------------------------------------------------------- ' Use: WAIT_SYNC ' -- wait until start of next servo frame (up to 20 mS) WAIT_SYNC: DO WHILE sync = IsOff LOOP RETURN ' ========================================================================= ' User Data ' ========================================================================= [/code] ---------- End of Message ---------- You can view the post on-line at: http://forums.parallax.com/forums/default.aspx?f=7&p=1&m=170452 Need assistance? Send an email to the Forum Administrator at forumadmin@parallax.com The Parallax Forums are powered by dotNetBB Forums, copyright 2002-2007 (http://www.dotNetBB.com)