Shop OBEX P1 Docs P2 Docs Learn Events
1/8 Scale Electric Locomotive — Parallax Forums

1/8 Scale Electric Locomotive

aroeskearoeske Posts: 5
edited 2014-04-18 20:24 in Robotics
About 3 years ago I was introduced to the hobby of "Live Steam Railroading." I decided I was going to build one of these, and so began this project. I decided electric was the way to go for me. So it didn't take long for me to decide I wanted to have a microprocessor running the show. I decided for the BS2 as I have has experience with it in the past. The following were the objectives I was going for:

1. Prototypical controls, I wanted a switch to control the direction and knob or lever to control the throttle.
2. The BS2 would control acceleration, to prevent bad things from happening if there are rapid control changes
3. I wanted a visual readout on the control box of the throttle settings and status.
4. When the unit was powered up, make sure all the controls were in a home position, do it doesn't just take off on you
5. Traction control, speed control.
6. Derail/collision detection, automatically set the throttle to 0 and apply the airbrakes
7. Determining the proximity of objects in front of the locomotive and apply brakes and 0 the throttle

I know this may be ambitious with this processor (I'm using the BS2e). I see it as a challenge to try and use the limited resources to accomplish this.

The physical dimensions, are as follows. It is 4 ft long, 16 inches wide and about 22 inches tall and weighs in at 350 pounds; yes you can ride it, well in a rider call right behind hit. I am using 2 12v deep cycle marine batteries hooked to a Dimension Engineering SyRen 50 controller, which takes a rc servo signal from the BS2e. Everything else runs off another 12v deep cycle battery.

Currently, 1,2,3 are done. 4 will be done shortly, I just resolved a reset issue today (Thank's Saffire!) and can put that code back in.

I have the accelerometer added and the program access it, but I haven't added the logic to control the systems based on the readings. That will require taking it out and determining the threshold for what is a derailment, etc.

While it may never be 100% complete, I hope to have it pretty much wrapped up this year. I will keep this updated as things move along. Comments and thoughts are welcome!

Here is the current code and I hope to have the schematic ready in a few days and I will post it here. Keep in mind this code is still in development, so don't laugh too hard!

Thanks

Andy
' {$STAMP BS2e}' {$PBASIC 2.5}


' ------------------------------------------------------------------------------
' Program Description
' ------------------------------------------------------------------------------
' Version: 0.4
' Date: 3/17/2014
' Changes: This version switchs to using a SyRen50 controller as opposed to
'          the scooter controller.  Including accell and decel routines as
'          the controller now has dynamic braking built in.
VerMajor         CON     0
VerMinor         CON     4




' ------------------------------------------------------------------------------
' I/O Definitions
' ------------------------------------------------------------------------------
SyRen           PIN     0                       ' ping to SyRen 50 controller
TX              CON     1                       ' serial output to LCD
' Accelerometer
CLKPin          PIN     4                       ' Clock Pin
DATAPin         PIN     6                       ' Data Pin
CSPin           PIN     8                       ' Chip Select Pin


DirFwd          CON     12                      ' set of Direction is set to forward
DirRev          CON     13                      ' set if Direction is reverse
Key             CON     14                      ' set if keyswitch is on
Pot             CON     15                      ' input from throttle
' ------------------------------------------------------------------------------
' Constants
' ------------------------------------------------------------------------------
OnTime          CON     10                      ' 10 milliseconds, BS2


MaxSpeed        CON     500                     ' Maximum Speed


' init the accelerometer
GOSUB InitAccel






' for the LCD
    T2400       CON     396
    T9600       CON     84
    T19K2       CON     32


LcdBaud         CON     T19K2


LcdBkSpc        CON     $08             ' move cursor left
LcdRt           CON     $09             ' move cursor right
LcdLF           CON     $0A             ' move cursor down 1 line
LcdCls          CON     $0C             ' clear LCD (use PAUSE 5 after)
LcdCR           CON     $0D             ' move pos 0 of next line
LcdBLon         CON     $11             ' backlight on
LcdBLoff        CON     $12             ' backlight off
LcdOff          CON     $15             ' LCD off
LcdOn1          CON     $16             ' LCD on; cursor off, blink off
LcdOn2          CON     $17             ' LCD on; cursor off, blink on
LcdOn3          CON     $18             ' LCD on; cursor on, blink off
LcdOn4          CON     $19             ' LCD on; cursor on, blink on
LcdLine1        CON     $80             ' move to line 1, column 0
LcdLine2        CON     $94             ' move to line 2, column 0


LcdCC0          CON     $F8             ' define custom char 0
LcdCC1          CON     $F9             ' define custom char 1
LcdCC2          CON     $FA             ' define custom char 2
LcdCC3          CON     $FB             ' define custom char 3
LcdCC4          CON     $FC             ' define custom char 4
LcdCC5          CON     $FD             ' define custom char 5
LcdCC6          CON     $FE             ' define custom char 6
LcdCC7          CON     $FF             ' define custom char 7


' ------------------------------------------------------------------------------
' Variables
' ------------------------------------------------------------------------------
curLevel        VAR     Word
setLevel        VAR     Word
Time            VAR     Word
char            VAR     Byte
idx1            VAR     Byte
isFwd           VAR     Bit
isRev           VAR     Bit
keyOn           VAR     Bit
counter         VAR     Nib
error           VAR     Nib
throtpercent    VAR     Word
firstTime       VAR     Nib


' Error codes
' 0 - no error good to go
' 1 - Throttle on at start up
' 2 - Rapid dir change
' 3 - Reverser on at startup
' 4 - Keyswitch on at startup




' ------------------------------------------------------------------------------
' Initialization
' ------------------------------------------------------------------------------
Reset:
  HIGH TX                               ' setup serial output pin
  PAUSE 100                             ' allow LCD to initialize


  SEROUT TX, LcdBaud, [LcdBLon]


' ------------------------------------------------------------------------------
' Program Code
' ------------------------------------------------------------------------------
Boot:
  ' Accel
  Address = MCTL: SendData = %01100101: GOSUB DataOut  'Set the Mode control register
                                                         'DATA ready status is NOT OUTPUT TO INT1 PIN
                                                         '3-wire SPI mode
                                                         'Self Test NOT enabled
                                                         '+/-2g sensitivity mode
                                                         'Measurement mode


  Address = XOFFL: SendData = XCal& $FF: GOSUB DataOut 'Write X-Axis Calibration Value ; LOWBYTE
  Address = XOFFH: SendData = XCal >> 8: GOSUB DataOut '                               ; HIGHBYTE


  Address = YOFFL: SendData = YCal& $FF: GOSUB DataOut 'Write Y-Axis Calibration Value ; LOWBYTE
  Address = YOFFH: SendData = YCal >> 8: GOSUB DataOut '                               ; HIGHBYTE


  Address = ZOFFL: SendData = ZCal& $FF: GOSUB DataOut 'Write Z-Axis Calibration Value ; LOWBYTE
  Address = ZOFFH: SendData = ZCal >> 8: GOSUB DataOut '                               ; HIGHBYTE


  DEBUG CLS                                           'Clear Display
  GOSUB TextField                                     'Draw TEXT field (stationary TEXT that does not get updated)




  ' Set custom Chars
  SEROUT TX, LcdBaud, [248,               ' Define Custom Character 0 Arrow Up
                       %00100,            '     *
                       %01110,            '   * * *
                       %10101,            ' *   *   *
                       %00100,            '     *
                       %00100,            '     *
                       %00100,            '     *
                       %00100,            '     *
                       %00100]            '     *
  SEROUT TX, LcdBaud, [249,               ' Define Custom Character 1 Arrow Down
                       %00100,            '     *
                       %00100,            '     *
                       %00100,            '     *
                       %00100,            '     *
                       %00100,            '     *
                       %10101,            ' *   *   *
                       %01110,            '   * * *
                       %00100]            '     *
  SEROUT TX, LcdBaud, [250,               ' Define Custom Character 2 Stop
                       %00100,            '     *
                       %01110,            '   * * *
                       %00100,            '     *
                       %00100,            '     *
                       %00100,            '     *
                       %10101,            ' *   *   *
                       %01110,            '   * * *
                       %00000]            '


'Run start up checks


  SEROUT TX, LcdBaud, [LcdCls]
  SEROUT TX, LcdBaud, [LcdOn1]
  ' Reverser Check
'  SEROUT TX, LcdBaud, [LcdCls]
'  SEROUT TX, LcdBaud, ["Reverser..."]
'  RevCheckTop:
'  IF IN12 = 1 AND IN13 = 1 THEN
'    GOTO RevGood
'  ENDIF
'  SEROUT TX, LcdBaud, [LcdCls]
'  SEROUT TX, LcdBaud, [LcdLine1,"Set Reverser",LcdLine2,"To off!"]
'  SEROUT TX, LcdBaud, [210,220]
'  PAUSE 250
'  GOTO RevCheckTop
'  RevGood:
'  PAUSE 250
  'Throttle Check
'  SEROUT TX, LcdBaud, [LcdCls]
'  SEROUT TX, LcdBaud, ["Throttle..."]
'  ThrCheckTop:
'  HIGH Pot
'  RCTIME Pot, 1, Time
'  IF Time < 2 THEN
'    GOTO ThrGood
'  ENDIF
'  SEROUT TX, LcdBaud, [LcdCls]
'  SEROUT TX, LcdBaud, [LcdLine1,"Set Throttle",LcdLine2,"To off!"]
'  SEROUT TX, LcdBaud, [210,220]
'  PAUSE 250
'  GOTO ThrCheckTop
'  ThrGood:
'  PAUSE 250
  'Keyswitch Check
'  SEROUT TX, LcdBaud, [LcdCls]
'  SEROUT TX, LcdBaud, ["Keyswitch..."]
'  KeyCheckTop:
'  IF IN14 = 1 THEN
'    GOTO KeyGood
'  ENDIF
'  SEROUT TX, LcdBaud, [LcdCls]
'  SEROUT TX, LcdBaud, [LcdLine1,"Set Ketswitch",LcdLine2,"To off!"]
'  SEROUT TX, LcdBaud, [210,220]
'  PAUSE 250
'  GOTO KeyCheckTop
'  KeyGood:


'  PAUSE 250




  SEROUT TX, LcdBaud, [LcdCls]
'  PAUSE 250


  counter=0
  error = 0


  curLevel=750
  firstTime = 1


Main:
  ' Get key switch position
  IF IN14 = 0 THEN
    keyOn = 1
  ELSE
    keyOn = 0
    ' Issue the stop command without deceleration, emergency stop
    curLevel = 750
    PULSOUT SyRen, curLevel
  ENDIF


  ' Get direction
  isRev = 0
  isFwd = 0
  IF IN12 = 0 THEN
    isFwd = 1
  ENDIF
  IF IN13 = 0 THEN
    isRev = 1
  ENDIF


  ' If the Keyswitch is off or no direction, then no need to get throttle
  IF keyOn = 1 AND isFwd <> isRev THEN
    ' Get pot Position
    HIGH Pot
    RCTIME Pot, 1, Time
  ELSE
    Time = 0
  ENDIF


  'Cap at 400
  'IF Time > 400 THEN
    'Time = 400
  'ENDIF


  'Convert for voltage
  setLevel = Time / 2
  throtpercent = Time / 5


  IF isRev = 1 THEN
    setLevel = 750 + setLevel
  ELSE
    setLevel = 750 - setLevel
  ENDIF


  ' This should help prevent jerking if the processor resets itself while moving
  IF firstTime = 1 THEN
    curLevel = setLevel
    firstTime = 0
  PULSOUT SyRen, curLevel
  SEROUT TX, LcdBaud, ["Version: ",DEC VerMajor,".",DEC VerMinor]
  PAUSE 2000
  ENDIF


  'DEBUG ? curLevel


  ' This gradually speeds up and slows down to prevent jerking
  IF curLevel > setLevel THEN
    curLevel = curLevel - 1
  ENDIF


  IF curLevel < setLevel THEN
    curLevel = curLevel + 1
  ENDIF


  ' Send the signal to the controller
  PULSOUT SyRen, curLevel


  ' Update display every 16 iterations
  IF counter = 0 THEN


    ' If the key switch is off we aren't going anyware
    IF keyOn = 0 THEN
      SEROUT TX, LcdBaud, [LcdLine2,"Throttle: ",DEC3 throtpercent,"%"]
      SEROUT TX, LcdBaud, [163,2]
      SEROUT TX, LcdBaud, [LcdLine1,"Controller Off"]


    ELSE


      ' Print current speed
      SEROUT TX, LcdBaud, [LcdLine2,"Throttle: ",DEC3 throtpercent,"%"]


      ' Print Direction
      IF isFwd = isRev THEN
        SEROUT TX, LcdBaud, [163,2]
      ENDIF
      IF isFwd = 1 THEN
        SEROUT TX, LcdBaud, [163,0]
      ENDIF
      IF isRev = 1 THEN
        SEROUT TX, LcdBaud, [163,1]
      ENDIF


      ' Overspeed
      IF Time > MaxSpeed THEN
        SEROUT TX, LcdBaud, [LcdLine1,"OVERSPEED!      "]
        SEROUT TX, LcdBaud, [208,220]
      ELSE
        SEROUT TX, LcdBaud, [LcdLine1,"                "]
      ENDIF
    ENDIF ' End keyOn=0
  ENDIF  ' End counter=0




  ' Check Acceleration every 16 iterations
  IF counter = 0 THEN
    ' Accel
    Address = XOUT8:GOSUB DataIn                        'Read in X-Axis Acceleration Value
    XAccel = ReceiveData|($FF00*ReceiveData.BIT7)          'Sign extend the two's complement byte so
                                                         'negative numbers can be properly displayed


    Address = YOUT8:GOSUB DataIn                        'Read in Y-Axis Acceleration Value
    YAccel = ReceiveData|($FF00*ReceiveData.BIT7)          'Sign extend the two's complement byte so
                                                         'negative numbers can be properly displayed


    Address = ZOUT8:GOSUB DataIn                        'Read in Z-Axis Acceleration Value
    ZAccel = ReceiveData|($FF00*ReceiveData.BIT7)          'Sign extend the two's complement byte so
                                                         'negative numbers can be properly displayed
    DEBUG CRSRXY,50,3, SDEC XAccel, "  ",               'Display the RAW X, Y, and Z Accelerometer values
          CRSRXY,50,4, SDEC YAccel, "  ",
          CRSRXY,50,5, SDEC ZAccel, "  "


  ENDIF




  counter = counter + 1
  'PAUSE 10
  GOTO Main                                    ' do it again


  InitAccel:
'Offset values FOR each axis:
XCal      CON 25    'VAR Word
YCal      CON 50    'VAR word
ZCal      CON 0     'VAR Word




XOUTL     CON $00   ' 10 bits output value X LSB             XOUT[7]  XOUT[6]  XOUT[5]  XOUT[4]  XOUT[3]  XOUT[2]  XOUT[1]  XOUT[0]
XOUTH     CON $01   ' 10 bits output value X MSB             --       --       --       --       --       --       XOUT[9]  XOUT[8]
YOUTL     CON $02   ' 10 bits output value Y LSB             YOUT[7]  YOUT[6]  YOUT[5]  YOUT[4]  YOUT[3]  YOUT[2]  YOUT[1]  YOUT[0]
YOUTH     CON $03   ' 10 bits output value Y MSB             --       --       --       --       --       --       YOUT[9]  YOUT[8]
ZOUTL     CON $04   ' 10 bits output value Z LSB             ZOUT[7]  ZOUT[6]  ZOUT[5]  ZOUT[4]  ZOUT[3]  ZOUT[2]  ZOUT[1]  ZOUT[0]
ZOUTH     CON $05   ' 10 bits output value Z MSB             --       --       --       --       --       --       ZOUT[9]  ZOUT[8]
XOUT8     CON $06   ' 8 bits output value X                  XOUT[7]  XOUT[6]  XOUT[5]  XOUT[4]  XOUT[3]  XOUT[2]  XOUT[1]  XOUT[0]
YOUT8     CON $07   ' 8 bits output value Y                  YOUT[7]  YOUT[6]  YOUT[5]  YOUT[4]  YOUT[3]  YOUT[2]  YOUT[1]  YOUT[0]
ZOUT8     CON $08   ' 8 bits output value Z                  ZOUT[7]  ZOUT[6]  ZOUT[5]  ZOUT[4]  ZOUT[3]  ZOUT[2]  ZOUT[1]  ZOUT[0]
STATUS    CON $09   ' Status registers                       --       --       --       --       --       PERR     DOVR     DRDY
DETSRC    CON $0A   ' Detection source registers             LDX      LDY      LDZ      PDX      PDY      PDZ      INT1     INT2
TOUT      CON $0B   ' "Temperature output value" (Optional)  TMP[7]   TMP[6]   TMP[5]   TMP[4]   TMP[3]   TMP[2]   TMP[1]   TMP[0]
'         CON $0C   ' (Reserved)                             --       --       --       --       --       --       --       --
I2CAD     CON $0D   ' I2C device address I                   2CDIS    DAD[6]   DAD[5]   DAD[4]   DAD[3]   DAD[2]   DAD[1]   DAD[0]
USRINF    CON $0E   ' User information (Optional)            UI[7]    UI[6]    UI[5]    UI[4]    UI[3]    UI[2]    UI[1]    UI[0]
WHOAMI    CON $0F   ' "Who am I" value (Optional)            ID[7]    ID[6]    ID[5]    ID[4]    ID[3]    ID[2]    ID[1]    ID[0]
XOFFL     CON $10   ' Offset drift X value (LSB)             XOFF[7]  XOFF[6]  XOFF[5]  XOFF[4]  XOFF[3]  XOFF[2]  XOFF[1]  XOFF[0]
XOFFH     CON $11   ' Offset drift X value (MSB)             --       --       --       --       --       XOFF[10] XOFF[9]  XOFF[8]
YOFFL     CON $12   ' Offset drift Y value (LSB)             YOFF[7]  YOFF[6]  YOFF[5]  YOFF[4]  YOFF[3]  YOFF[2]  YOFF[1]  YOFF[0]
YOFFH     CON $13   ' Offset drift Y value (MSB)             --       --       --       --       --       YOFF[10] YOFF[9]  YOFF[8]
ZOFFL     CON $14   ' Offset drift Z value (LSB)             ZOFF[7]  ZOFF[6]  ZOFF[5]  ZOFF[4]  ZOFF[3]  ZOFF[2]  ZOFF[1]  ZOFF[0]
ZOFFH     CON $15   ' Offset drift Z value (MSB)             --       --       --       --       --       ZOFF[10] ZOFF[9]  ZOFF[8]
MCTL      CON $16   ' Mode control                           LPEN     DRPD     SPI3W    STON     GLVL[1]  GLVL[0]  MOD[1]   MOD[0]
INTRST    CON $17   ' Interrupt latch reset                  --       --       --       --       --       --       CLRINT2  CLRINT1
CTL1      CON $18   ' Control 1                              --       THOPT    ZDA      YDA      XDA      INTRG[1] INTRG[0] INTPIN
CTL2      CON $19   ' Control 2                              --       --       --       --       --       DRVO     PDPL     LDPL
LDTH      CON $1A   ' Level detection threshold limit value  LDTH[7]  LDTH[6]  LDTH[5]  LDTH[4]  LDTH[3]  LDTH[2]  LDTH[1]  LDTH[0]
PDTH      CON $1B   ' Pulse detection threshold limit value  PDTH[7]  PDTH[6]  PDTH[5]  PDTH[4]  PDTH[3]  PDTH[2]  PDTH[1]  PDTH[0]
PW        CON $1C   ' Pulse duration value                   PD[7]    PD[6]    PD[5]    PD[4]    PD[3]    PD[2]    PD[1]    PD[0]
LT        CON $1D   ' Latency time value                     LT[7]    LT[6]    LT[5]    LT[4]    LT[3]    LT[2]    LT[1]    LT[0]
TW        CON $1E   ' Time window for 2nd pulse value        TW[7]    TW[6]    TW[5]    TW[4]    TW[3]    TW[2]    TW[1]    TW[0]
'         CON $1F   ' (Reserved)                             --       --       --       --       --       --       --       --


XAccel    VAR Word  ' Variables to store incoming RAW data from the accelerometer
YAccel    VAR Word
ZAccel    VAR Word


'XMax      VAR Word
'YMax      VAR Word
'ZMax      VAR Word


Address   VAR Word  ' Variables for reading and writing data to the acclerometer
SendData  VAR Byte
ReceiveData VAR Byte


'
'         MCTL - Mode control register
'   +---------------------------------------+
'   ¦ D7 ¦ D6 ¦ D5 ¦ D4 ¦ D3 ¦ D2 ¦ D1 ¦ D0 ¦
'   +----+----+----+----+----+----+----+----¦
'   ¦ -- ¦DRPD¦SPI3¦STON¦GLVL¦GLVL¦MODE¦MODE¦
'   +---------------------------------------+
'
'
'   D7       - don't care          0
'
'   D6(DRPD) - DATA ready status   0 - OUTPUT TO INT1 PIN
'                                  1 - is NOT OUTPUT TO INT1 PIN
'
'   D5(SPI3W)- Wire Mode           0 - SPI is 4-wire mode
'                                  1 - SPI is 3-wire mode
'
'   D4(STON) - Self Test           0 - NOT enabled
'                                  1 - enabled
'
'   D3(GLVL[1]) - g-SELECT        00 - 8g ; 16 LSB/g in 8-Bit format
'   D2(GLVL[0]) - g-SELECT        10 - 4g ; 32 LSB/g in 8-Bit format
'                                 01 - 2g ; 64 LSB/g in 8-Bit format
'
'                                         ; Note: When reading g in 10-Bit
'                                         ;       format, resolution is fixed
'                                         ;       at 64 LSB/g
'                   10-Bit g register
'   +-------------------------------------------------+
'   ¦ D9 ¦ D8 ¦ D7 ¦ D6 ¦ D5 ¦ D4 ¦ D3 ¦ D2 ¦ D1 ¦ D0 ¦
'   +-------------------------------------------------+
'   ¦<------------------------------------->¦            ; These 8 bits are READ in 8g mode
'        ¦<------------------------------------->¦       ; These 8 bits are READ in 4g mode
'             ¦<------------------------------------->¦  ; These 8 bits are READ in 2g mode
'
'   D1(MODE[1]) - Mode SELECT     00 - Standby
'   D0(MODE[0]) - Mode SELECT     01 - Measurement
'                                 10 - Level Detection
'                                 11 - Pulse Detection
RETURN


DataOut:
LOW CSPin                                              'Pull chip select pin low to start transmission
SHIFTOUT DATAPin, CLKPin, MSBFIRST, [(Address|%1000000)<<1] 'Select register Address
SHIFTOUT DATAPin, CLKPin, MSBFIRST, [SendData]         'Write value to Address
HIGH CSPin                                             'End transmission
RETURN


DataIn:
LOW CSPin                                              'Pull chip select pin low to start transmission
SHIFTOUT DATAPin, CLKPin, MSBFIRST, [Address<<1]       'Select register Address
SHIFTIN DATAPin, CLKPin, MSBPRE, [ReceiveData]         'Read value from Address
HIGH CSPin                                             'End transmission
RETURN


TextField:
DEBUG CRSRXY,40,0,"MMA7455 3-Axis Accelerometer BS2 DEMO #1",   'Display all stationary TEXT that does not get updated
      CRSRXY,48,2,"8-Bit 2g Mode ; 64 LSB/g",
      CRSRXY,48,3, "X=",
      CRSRXY,48,4, "Y=",
      CRSRXY,48,5, "Z="
RETURN

Comments

  • abecedarianabecedarian Posts: 312
    edited 2014-04-15 22:56
    This sounds totally awesome!

    I could suggest use an accelerometer to limit speed around corners, when possible. Also, same to limit throttle and braking so you don't lose traction. Since you're using a pot, maybe a servo or stepper could apply force feedback letting you know you're exceeding programmed limits?

    And then you have to puff steam and smoke... and blow the whistle. ;)
  • NWCCTVNWCCTV Posts: 3,629
    edited 2014-04-17 19:14
    Some pics and/or video would be awesome!!!!
  • aroeskearoeske Posts: 5
    edited 2014-04-18 20:24
    Here are a couple images, an external one as well one of the main electronics board.

    IMGP0022.jpg
    IMG_20140330_192558.jpg
    1024 x 768 - 95K
    1024 x 576 - 84K
Sign In or Register to comment.