May 02, 2024, 08:37:04 PM

News:

Got VSA?  Want to use your Prop-SX?  Now you can!  See the VSA section of the Library forum for Prop-SX code that works with VSA.


6 Channel Servo and 10 Channel Relay...Is it possible?

Started by Ryanm0085, August 20, 2009, 06:21:24 PM

Previous topic - Next topic

Ryanm0085

I am trying to control a 3-Axis skull using vsa.  Its working great.  However, since i only am using 6 servos, two for the eyes, i am wasting the other 2 channels.  Is there any way to make this a relay output?

JonnyMac

If you're up for some fun you could modify the 8+8 program so that it has six servo channels plus 10 digital channels.  If you get stumped, let me know.
Jon McPhalen
EFX-TEK Hollywood Office

JonnyMac

August 20, 2009, 07:29:51 PM #2 Last Edit: August 25, 2009, 06:07:05 PM by JonnyMac
Okay, it's another one of those nights with Chinese takeout at my desk, but as I've got it covered with other boards at the moment I can't test this -- still, I feel pretty confident.  If you have troubles before I can dump it into a Prop-SX please let me know.

Updated: 25 AUG 2009

' =========================================================================
'
'   File...... Servo6_Digital10.SXB
'   Purpose...
'   Author.... Jon Williams, EFX-TEK
'              Copyright (c) 2008-2009 EFX-TEK
'              Some Rights Reserved
'              -- see http://creativecommons.org/licenses/by/3.0/
'   E-mail.... jwilliams@efx-tek.com
'   Started...
'   Updated... 25 AUG 2009
'
' =========================================================================


' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------
'
' Servo controller/output device designed for use with VSA or other
' real-time serial control programs.
'
'   P0 to P5.... Servo control
'   P6 to P15... Digitial outputs
'
' The protocol is identical to the SEETRON (www.seetron.com) MiniSSC:
'
'   <sync><channel><value>
'
'   sync...... $FF (255)
'
'   channel... 0 to  5 for servos
'              6 to 15 for digital outputs
'
'   value..... 55 to 245 for servos (150 = center)
'              >127 = on for digital channels
'              <128 = off for digital channels
'
' Default baud rate is 38.4K but can be changed down to as low as 2400.


' -------------------------------------------------------------------------
' Conditional Compilation Symbols
' -------------------------------------------------------------------------


' -------------------------------------------------------------------------
' Device Settings
' -------------------------------------------------------------------------

ID              "Srvo6+10"

DEVICE          SX28, OSCHS2, BOR42
FREQ            50_000_000


' -------------------------------------------------------------------------
' I/O Pins
' -------------------------------------------------------------------------

OutsHi          PIN     RC   OUTPUT             ' solenoid control outputs
Out9           PIN     RC.7                    ' use P15/OUT15
Out8           PIN     RC.6                    ' use P14/OUT14
Out7           PIN     RC.5                    ' use P13/OUT13
Out6           PIN     RC.4                    ' use P12/OUT12
Out5           PIN     RC.3                    ' use P11/OUT11
Out4           PIN     RC.2                    ' use P10/OUT10
Out3           PIN     RC.1                    ' use P9/OUT9
Out2           PIN     RC.0                    ' use P8/OUT8

OutsLo          PIN     RB   OUTPUT
Out1           PIN     RB.7                    ' use P7/OUT7
Out0           PIN     RB.6                    ' use P6/OUT6

ServoCtrl       PIN     RB   OUTPUT             ' servo control pins
Servo5         PIN     RB.5                    ' use P5
Servo4         PIN     RB.4                    ' use P4
Servo3         PIN     RB.3                    ' use P3
Servo2         PIN     RB.2                    ' use P2
Servo1         PIN     RB.1                    ' use P1
Servo0         PIN     RB.0                    ' use P0

TX              PIN     RA.3 OUTPUT             ' to PC
RX              PIN     RA.2 INPUT              ' from PC
SCL             PIN     RA.1 INPUT              ' EE clock line (I2C)
SDA             PIN     RA.0 INPUT              ' EE data line (I2C)

' Note: TX, SCL, and SDA lines are not used by this program


' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------

IsOn            CON     1
IsOff           CON     0

Yes             CON     1
No              CON     0

LO_LIMIT        CON     55                      ' to prevent servo burn-up
HI_LIMIT        CON     245


' Bit dividers for 3.255 uS interrupt
' -- ISR actually runs at 3.333 uS for better servo timing

Baud2400        CON     128
Baud4800        CON     64
Baud9600        CON     32
Baud19K2        CON     16
Baud38K4        CON     8

Baud1x0         CON     Baud38K4                ' 1 bit period (ISR counts)
Baud1x5         CON     Baud1x0 * 3 / 2         ' 1.5 bit periods


' -------------------------------------------------------------------------
' Variables
' -------------------------------------------------------------------------

flags           VAR     Byte                    ' (keep global)
isrFlag        VAR     flags.0
rxReady        VAR     flags.1                 ' rx byte waiting

sync            VAR     Byte
chan            VAR     Byte
value           VAR     Byte
mask            VAR     Byte

rxSerial        VAR     Byte (16)
rxBuf          VAR     rxSerial(0)             ' 8-byte buffer
rxCount        VAR     rxSerial(8)             ' rx bit count
rxDivide       VAR     rxSerial(9)             ' bit divisor timer
rxByte         VAR     rxSerial(10)            ' recevied byte
rxHead         VAR     rxSerial(11)            ' buffer head (write to)
rxTail         VAR     rxSerial(12)            ' buffer tail (read from)
rxBufCnt       VAR     rxSerial(13)            ' # bytes in buffer

svoData         VAR     Byte (16)               ' bank servo data
pos            VAR     svoData(0)              ' position table
pos0           VAR     svoData(0)
pos1           VAR     svoData(1)
pos2           VAR     svoData(2)
pos3           VAR     svoData(3)
pos4           VAR     svoData(4)
pos5           VAR     svoData(5)
pos6           VAR     svoData(6)
pos7           VAR     svoData(7)
svoTix         VAR     svoData(8)              ' isr divider
svoFrame_LSB   VAR     svoData(9)              ' frame timer
svoFrame_MSB   VAR     svoData(10)
svoIdx         VAR     SvoData(11)             ' active servo pointer
svoTimer       VAR     svoData(12)             ' pulse timer
svoPin         VAR     svoData(13)             ' active servo pin



' =========================================================================
 INTERRUPT NOPRESERVE 300_000                  ' (4)   run every 3.333 uS
' =========================================================================

Mark_ISR:
 \ SETB  isrFlag                               ' (1)


' -------
' RX UART
' -------
'
' UART code by C. Gracey, A. Williams, et al
' -- buffer and flow control mods by Jon Williams
'
Receive:
 ASM
   MOV   FSR, #rxSerial                        ' (2)
   JB    rxBufCnt.3, RX_Done                   ' (2/4) skip if buffer is full
   MOVB  C, RX                                 ' (4)   sample serial input
   TEST  rxCount                               ' (1)   receiving now?
   JNZ   RX_Bit                                ' (2/4) yes, get next bit
   MOV   W, #9                                 ' (1)   no, prep for next byte
   SC                                          ' (1/2)
    MOV  rxCount, W                            ' (1)   if start, load  bit count
   MOV   rxDivide, #Baud1x5                    ' (2)   prep for 1.5 bit periods

RX_Bit:
   DJNZ  rxDivide, RX_Done                     ' (2/4) complete bit cycle?
   MOV   rxDivide, #Baud1x0                    ' (2)   yes, reload bit timer
   DEC   rxCount                               ' (1)   update bit count
   SZ                                          ' (1/2)
    RR   rxByte                                ' (1)   position for next bit
   SZ                                          ' (1/2)
    JMP  RX_Done                               ' (3)

RX_Buffer:
   MOV   W, #rxBuf                             ' (1)   point to buffer head
   ADD   W, rxHead                             ' (1)
   MOV   FSR, W                                ' (1)
   MOV   IND, rxByte                           ' (2)   move rxByte to head
   INC   rxHead                                ' (1)   update head
   CLRB  rxHead.3                              ' (1)   keep 0..7
   INC   rxBufCnt                              ' (1)   update buffer count
   SETB  rxReady                               ' (1)   set ready flag

RX_Done:
 ENDASM


' ----------------
' Servo Processing
' ----------------
'
Test_Servo_Tix:
 ASM
   BANK  svoData                               ' (1)
   INC   svoTix                                ' (1)   update divider
   CJB   svoTix, #3, Servo_Done                ' (4/6) done?
   CLR   svoTix                                ' (1)   yes, reset for next

' Code below this point runs every 10 uS

Check_Frame_Timer:
   CJNE  svoFrame_LSB, #2000 & 255, Inc_FrTmr  ' (4/6) svoFrame = 2000 (20 ms)?
   CJNE  svoFrame_MSB, #2000 >>  8, Inc_FrTmr  ' (4/6)
   CLR   svoFrame_LSB                          ' (1)   yes, reset
   CLR   svoFrame_MSB                          ' (1)
   MOV   svoPin, #%0000_0001                   ' (2)   start servo sequence
   CLR   svoIdx                                ' (1)   point to servo 0
   MOV   FSR, #pos                             ' (2)
   MOV   svoTimer, IND                         ' (2)
   JMP   Refesh_Servo_Outs                     ' (3)

Inc_FrTmr:
   INC   svoFrame_LSB                          ' (1)   DEC svoFrame
   ADDB  svoFrame_MSB, Z                       ' (2)

Check_Servo_Timer:
   TEST  svoPin                                ' (1)   any servos on?
   SNZ                                         ' (1)
    JMP  Servo_Done                            ' (1)   no, exit
   DEC   svoTimer                              ' (1)   yes, update timer
   SZ                                          ' (1)   still running?
    JMP  Servo_Done                            ' (1)   yes, exit

Reload_Servo_Timer:
   INC   svoIdx                                ' (1)   point to next servo
   MOV   W, #pos                               ' (1)   get pulse timing
   ADD   W, svoIdx                             ' (1)
   MOV   FSR, W                                ' (1)
   MOV   W, IND                                ' (1)
   MOV   svoTimer, W                           ' (1)   move to timer

Select_Next_Servo:
   CLC                                         ' (1)
   RL    svoPin                                ' (1)
   AND   svoPin, #%0011_1111                   ' (2)   limit servo channels

Refesh_Servo_Outs:
   AND   ServoCtrl, #%1100_0000                ' (2)   clear last
   OR    ServoCtrl, svoPin                     ' (2)   update outputs

Servo_Done:
 ENDASM



ISR_Exit:
 RETURNINT                                     ' (4)


' -------------------------------------------------------------------------
' Subroutine / Function Declarations
' -------------------------------------------------------------------------

RX_BYTE         FUNC    1, 0                    ' receive a byte


' =========================================================================
 PROGRAM Start
' =========================================================================

Start:
 TX = 1                                        ' set TX line to idle

 ' center servos
 PUT pos, 150, 150, 150, 150, 150, 150


Main:
 sync = RX_BYTE
 IF sync <> $FF THEN Main


Get_Channel:
 chan = RX_BYTE
 IF chan = $FF THEN Get_Channel                ' correct for re-sync
 IF chan > 15 THEN Main                        ' check channel range


Get_Value:
 value = RX_BYTE
 IF value = $FF THEN Get_Channel               ' correct for re-sync


Process_Value:
 IF chan < 6 THEN                              ' servo channel?
   value = value MIN LO_LIMIT                  ' force to legal limits
   value = value MAX HI_LIMIT
   pos(chan) = value
   GOTO Main
 ELSE
   IF chan < 8 THEN
     GOTO Dig_Lo
   ELSE
     GOTO Dig_Hi
   ENDIF
 ENDIF


Dig_Lo:
 chan = 1 << mask
 IF value.7 = 1 THEN                           ' >127?
   OutsLo = OutsLo | mask                      ' yes, activate output
 ELSE
   OutsLo = OutsLo &~ mask                     ' no, deactivate output
 ENDIF
 GOTO Main


Dig_Hi:
 chan.3 = 0                                    ' align for control port
 mask = 1 << chan                              ' make channel bit mask
 IF value.7 = 1 THEN                           ' >127?
   OutsHi = OutsHi | mask                      ' yes, activate output
 ELSE
   OutsHi = OutsHi &~ mask                     ' no, deactivate output
 ENDIF
 GOTO Main


' -------------------------------------------------------------------------
' Subroutine / Function Code
' -------------------------------------------------------------------------

' Use: aByte = RX_BYTE
' -- returns "aByte" from 8-byte circular buffer
' -- will wait if buffer is presently empty
' -- rxBufCnt holds byte count of receive buffer (0 to 8)

FUNC RX_BYTE
 ASM
   JNB   rxReady, @$                           ' wait if empty
   MOV   FSR, #rxSerial                        ' point to serial vars
   MOV   W, #rxBuf
   ADD   W, rxTail                             ' point to rxBuf(rxTail
   MOV   FSR, W
   MOV   __PARAM1, IND                         ' get byte at tail
   INC   rxTail                                ' update tail
   CLRB  rxTail.3                              ' keep 0..7
   DEC   rxBufCnt                              ' update buffer count
   SNZ                                         ' exit if not zero
    CLRB rxReady                               ' else clear ready flag
   MOV   FSR, #__DEFAULT
 ENDASM
 ENDFUNC


' =========================================================================
' User Data
' =========================================================================
Jon McPhalen
EFX-TEK Hollywood Office

JonnyMac

Note that I've updated the program above -- I found some problems in the six-channel servo code while porting it to the EZ-8.
Jon McPhalen
EFX-TEK Hollywood Office