November 23, 2024, 06:21:45 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.


Prop-SX - 8 Servos plus 8 Digital Outs with VSA

Started by JonnyMac, February 26, 2008, 03:55:38 PM

Previous topic - Next topic

JonnyMac

February 26, 2008, 03:55:38 PM Last Edit: June 16, 2009, 10:06:51 AM by JonnyMac
There's no doubt the VSA has become the defacto standard for servo control with props and many customers have asked us to "get compatible" with VSA.  Honestly, we didn't know how so we downloaded the demo and found it's really not too tough.

The program below can be run by VSA and will give you eight servo outputs on P0 to P7 and eight digital (relay) outputs on P8 to P15.  Once you've downloaded the program you connect your PC to the DB-9 connector on the Prop-SX.

You'll want to configure your VSA project like this:

Channels: 0 to 15

Channels 0 to 7:
  * MiniSSC Servo
  * +Value = 245
  * -Value = 55
  * Default = 150

Channels 8 to 15:
  * MiniSSC Relay
  * +Value = 254
  * -Value = 0
  * Default = 0

Set your COM port to 38400.

[Edit]: Posted updated version 16 JUN 2009


' =========================================================================
'
'   File...... Servo8_Digital8.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... 16 JUN 2009
'
' =========================================================================


' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------
'
' Servo controller/output device designed for use with VSA or other
' real-time serial control programs.
'
'   P0 to P7.... Servo control
'   P8 to P15... Digitial outputs
'
' The protocol is identical to the SEETRON (www.seetron.com) MiniSSC:
'
'   <sync><channel><value>
'
'   sync...... $FF (255)
'
'   channel... 0 to  7 for servos
'              8 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              "Servo8+8"

DEVICE          SX28, OSCHS2, TURBO, STACKX, OPTIONX, BOR42
FREQ            50_000_000


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

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

ServoCtrl       PIN     RB   OUTPUT             ' servo control pins
Servo7         PIN     RB.7                    ' use P7
Servo6         PIN     RB.6                    ' use P6
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, #%00000001                    ' (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
    CLRB  svoidx.3                              ' (1)   keep 0 - 7
    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)

Refesh_Servo_Outs:
    MOV   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, 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 < 8 THEN                              ' servo channel?
    value = value MIN LO_LIMIT                  ' force to legal limits
    value = value MAX HI_LIMIT
    pos(chan) = value
  ELSE
    chan.3 = 0                                  ' align for control port
    mask = 1 << chan                            ' make channel bit mask
    IF value.7 = 1 THEN                         ' >127?
      Outs = Outs | mask                        ' yes, activate output
    ELSE
      Outs = Outs &~ mask                       ' no, deactivate output
    ENDIF
  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

gmacted

Jon,

     I just ordered a prop-sx starter kit (it should be delivered by the time I get home today), and I plan on controlling 8 servos using VSA.  I have a question about the connections.  From what I understand, which is very little at this point, is that the servos will be connected to P0 - P7.  Will I be able to power the servos using an external power source?  The power supply I will be using has two outputs +12V @3A and + 5V @ 5A.  The +12V will be used to power the Prop-SX.  You have on on-board regualtor (I'm assuming +5V?) that supplies power to the on-board logic.  I need to use external +5V to power the servos.  Can this be done since the P0 output is based on the on-board regualtor?

JonnyMac

You'll have to build an adapter to use external power; just make sure that your external supply is no more than 6v (double-check this with the servo vendor) and that you connect the ground side of your external supply to ground on the Prop-SX (GND terminal or any of the Px.B connections).

You can build a little power adapter from this schematic:



... using our Proto PCB (http://www.efx-tek.com/topics/proto_pcb.html).  The terminal block and male pin headers you can get from Mouser Electronics -- here are the part numbers I use:

* Terminal block: 571-2828362
* Male header: 517-6111TG
    -- this is a 40-pin header; you can cut this down to strips of 8 -- use 3 to make a 3x8 header for servos
Jon McPhalen
EFX-TEK Hollywood Office

gmacted

Jon,

     Not to be picky, but I just noticed that the code listed in the first post is the Pulse Width modulation code, not the digital output code.  The attached file is correct.  I downloaded the code to start to figure out how it worked and noticed this problem.  To avoid confusion, you should probably fix that.

JonnyMac

Sorry about that -- goes to show that I'm human (despite rumors to the contrary).

I have posted the correct program, and it has been freshened a bit (the attached file was replaced, too).
Jon McPhalen
EFX-TEK Hollywood Office