Software - 16F88 Controller - controls the movement of the mining
train as it climbs the mountain on switch backs - 3 servos for switches
and 7 reed switches for sensors '10-6-10- this one (v 8.0x-XP) seems to be working with the single mainline laser
'10-05-10 - decel changed so trains stop more rapidly
'NOTE - 10-5-10 - may have figured out how to program this from Win 7 - see note below
'NOTE: program in programmer (no ICSP) using old IBM laptop Microcode Studio 2.46
'CONFIRMED 8-26-10 - must use old XP laptop! IBM /w 2.46 to get it to work!
'Note that ICSP does not work with MCLR off & pin 4 used as input
'commands - OK start / stop
'Chan + faster / Chan - slower
'Volume + direction L to R / Volume - direction R to L
'FF more stop time / RW less stop time
' ENTER - input stop time digits 0-99 (two digits only)
DEFINE DEBUG_REG PORTA
DEFINE DEBUG_BIT 2 ' PIN 1 on 16f88
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 1 ' Set Debug mode: 0 = true, 1 = inverted
'NOTE 10-4-10 - find that this line is not needed if you set fuses manually in the programmer
' not fully tested but seems to be the case. Make sure the CCP is set to RB0, not RB3
@ DEVICE PIC16F88, INTRC_OSC_NOCLKOUT, WDT_OFF, LVP_OFF, PWRT_ON, PROTECT_OFF, BOD_ON, MCLR_OFF
DEFINE OSC 8
OSCCON = $70 'dec 112 binary 11100000 = 8mhz
'NOTE - at $70 (8mhz) must double ms on GETIR routines to 400 & 200
'Include "modedefs.bas"
loop VAR BYTE
temp VAR WORD
temp1 VAR WORD
temp2 VAR WORD
LEDTemp1 VAR BYTE
LEDTemp2 VAR BYTE
LEDTemp3 VAR BYTE
Laps VAR WORD
ReportLapsTime VAR WORD
TempByte VAR BYTE
digit VAR BYTE
rndYN VAR BYTE
PauseByte VAR BYTE 'pause at end of run in seconds
PauseWord VAR WORD 'used in lap report correction of pause
SavePause VAR BYTE 'temp variable to store value while working
SaveADRate VAR BYTE 'temp variable to store value while working
SaveSpeed VAR BYTE 'temp variable to store value while working
PauseByte2 VAR BYTE
DigitsByte VAR BYTE 'temp for getting digit input
DigitType VAR BYTE '1 =speed, 2=pause, 3=ADRate
ADRate VAR BYTE 'accel / decel rate - large # is fast rate
TempWord VAR WORD
TempWord2 VAR WORD
TempWord3 VAR WORD
value VAR BYTE
ForwardFlag VAR BIT
InBlockFlag VAR BIT '0 if on mainline / 1 if in block
ReedSW5 VAR porta.0 'pin 17 - reed in mountain
ReedSW1 VAR porta.1 'pin 18 -lowest reed
SerialPin VAR porta.2 'used by debug not as SerialPin
ReedSW3 VAR porta.3 'pin 2 - center right reed
ReedSW2 VAR porta.4 'pin 3 - lower left reed
MainLine VAR porta.5 'pin 4
ReedSWX7 VAR porta.6 'pin 15 - positioned lower side of xover
ReedSWX6 VAR porta.7 'pin 16 - positioned upper side of xover
'NOTE: swapped 6 & 7 8-26-10
TIP101 CON 2 'pin 6 for PWM port b.0
ReedSW4 VAR portb.1 'pin 7 - upper left reed
ServoSW3 VAR portb.2 'pin 8
relay VAR portb.3 'relay to control Direction pin 9
ServoSW1 VAR portb.4 'pin 10
ServoSW2 VAR portb.5 'pin 11
BlueLED VAR portb.6 'pin 12
IRin VAR portB.7 'pin 13
StoppedTrain VAR BIT 'shows train stopped or not =1 on stopped
StopTime VAR WORD 'time to stop after reverse in siding
zero CON 136
one CON 128
two CON 129
three CON 130
four CON 131
five CON 132
six CON 133
seven CON 134
eight CON 135
nine CON 136
channelUP CON 144
channelDOWN CON 145
volumeUP CON 146
volumeDOWN CON 147
OK CON 148
Menu CON 224
ENTER CON 139
Power CON 149
TVVCR CON 165
FF CON 29
RW CON 28
Speed VAR BYTE
Direction VAR BIT
MainLineThereFlag VAR BIT '=0 if no main line / =1 if there
StopForMainLineFlag VAR BIT 'set if stop conditions exist
StoppedAtXingFlag VAR BIT ' set to 1 if stopped waiting for mainline to clear
ReedSWX6HitFlag VAR BIT 'shows that reedsw6 was hit once
ReedSWX7HitFlag VAR BIT 'shows that reedsw7 was hit once
IRpulse_length VAR WORD(13)
xx VAR BYTE
Command VAR BYTE
VersionWhole VAR BYTE
VersionDecimal VAR BYTE
UP CON 1 'for Direction relay
DOWN CON 0 'for Direction relay
Straight CON 1 'for turnouts
Turned CON 0 'for turnouts
Hit CON 0 'for reed switches
RtoL CON 0 'for right to left relay
LtoR CON 1 'for right to left relay
Yes CON 0 'is main line train on track?
No CON 1 'is main line train on track?
ansel = 0
cmcon = 7
trisa = %11111011
trisb = %10000010
Delay VAR WORD
Delay=15
CW1 CON 265
CCW1 CON 320
CW2 CON 265
CCW2 CON 320
CW3 CON 255
CCW3 CON 315
PWMFreq CON 2200
VersionWhole = 8
VersionDecimal = 0
MainLineThereFlag = 0 '=0 when no main line active
StopForMainLineFlag = 0 'indicates no main line train there
StoppedAtXingFlag = 0
laps=0
HIGH blueled
DATA @0,150,005, 1, 3 '150 speed, 005 pause, 001 adrate (1 is slow rate)
'stoptime = 5 sec
READ 0, speed
READ 1, pausebyte
READ 2, ADRate
READ 3, stoptime
HPWM TIP101, 0, 0 'all stop
DEBUG 10,13,10,13,10,13,10,13,10,13,10,13
'Debug 10,13,10,13,"Module Controller -SERVOS- (c) TrainElectronics.com",10,13
DEBUG "10-06-10 - Version ",#versionwhole,".",#versiondecimal,"x XP" ,10,13
DEBUG "no ICSP",10,13
PAUSE 2000
LOW servosw1:LOW servosw2:LOW servosw3
temp=0
ReedSWX6HitFlag =0
ReedSWX7HitFlag =0
VeryTop:
temp=temp+1
'debug 10,13,"15, 16, 4 ",#porta.6," ",#porta.7," ",#porta.5 , " ",#temp
'pause 500
'goto VeryTop:
relay = UP 'Direction
Direction=UP '1=up, 0=down
tempword=0
command=0
forwardflag=0
InBlockFlag=0
stoppedtrain=0
start0:
'low sound2:pause 100:high sound2 ' ring bell
PAUSE 500
LOW blueled
DEBUG 10,13,"@ vt",10,13
GOSUB accel:PAUSE 200 'pause to get out of block - may help?
Start01:
WaitForReed:
'mainline = 0 if there is no train on main line track - =1 if train is there!
IF mainline=0 AND stoppedatxingflag = 1 THEN ' train cleared after stop
GOSUB accel :DEBUG "@ restart!",10,13
stoppedatxingflag=0
mainlinethereflag=0
ENDIF
'if mainline=yes and mainlinethereflag=0 then ' signal from other board that train is there
' mainlinethereflag=1
' debug "MLTF= ",#mainlinethereflag,10,13 'XXXXXXXXXXX Error here - reports this even if ML not there - causes loco to pause
' 'Pause 500
'endif
command=0
TOGGLE blueled
IF IRin = 0 THEN GOSUB GetIR
start02:
IF command=OK THEN ' stop if running if OK hit or start if stopped
StoppedTrain=NOT(stoppedtrain)
DEBUG "Stopped ",#stoppedtrain,10,13
PAUSE 200
command=0
IF stoppedtrain = 1 THEN '=1 if stopped
HPWM TIP101, 0, 0
PAUSE 1000
ENDIF
IF stoppedtrain = 0 THEN GOSUB accel
ENDIF
IF command=0 THEN skipit0:
IF command = channelUP THEN speedup:
IF command = channelDOWN THEN speeddown:
IF command = volumeDOWN THEN relayoff:
IF command = volumeUP THEN relayon:
IF command = FF THEN IncreaseStopTime
IF command = RW THEN DecreaseStopTime
IF command = ENTER THEN GetDigits:
skipit0:
'debug #reedsw1," ",#reedsw2," ",#reedsw3," ",#reedsw4," ",#reedsw5,10,13: ''," Speed= ",#speed,10,13:goto verytop:
IF reedsw1=1 AND reedsw2=1 AND reedsw3=1 AND reedsw4=1 AND reedsw5=1_' then waitforreed:_
AND ReedSWX6 =1 AND ReedSWX7 =1 THEN waitforreed:
IF (ReedSWX6 = Hit AND direction = UP) OR (ReedSWX7 = Hit AND direction = DOWN) THEN
DEBUG "Xing Hit dir=",#direction,10,13
IF mainline=1 THEN
DEBUG "stopped @ xing",10,13
IF MainLineThereFlag = 1 THEN 'set stop conditions
IF StopForMainLineFlag = 1 THEN
HPWM TIP101,0,0:LOW TIP101 'gosub decel
StoppedAtXingFlag = 1
ENDIF
ENDIF
HPWM TIP101,0,0:LOW TIP101
stoppedatxingflag=1
ENDIF
ENDIF
GOTO skip1
IF ReedSWX6 = Hit AND ReedSWX6HitFlag =0 AND direction = UP THEN ' - positioned lower side of xover
DEBUG "swx6 hit" ,10,13
ReedSWX6HitFlag =1:ReedSWX7HitFlag =0
IF MainLineThereFlag = 1 THEN 'set stop conditions
IF StopForMainLineFlag = 1 THEN
HPWM TIP101,0,0:LOW TIP101 'gosub decel
StoppedAtXingFlag = 1
ENDIF
ENDIF
IF direction = DOWN THEN stopformainlineflag=0
ENDIF
IF ReedSWX7 = Hit AND ReedSWX7HitFlag=0 AND direction = DOWN THEN ' - positioned upper side of xover
DEBUG "swx7 hit" ,10,13
ReedSWX6HitFlag =0:ReedSWX7HitFlag =1
IF MainLineThereFlag = 1 THEN 'set stop conditions
IF StopForMainLineFlag = 1 THEN
HPWM TIP101,0,0:LOW TIP101 'gosub decel
StoppedAtXingFlag = 1
ENDIF
ENDIF
IF direction = UP THEN stopformainlineflag=0
ENDIF
skip1:
IF reedsw1=Hit THEN 'and Direction = down then
DEBUG "1 hit dn",10,13
GOSUB ResetFlags
GOSUB decel
GOSUB StopBetweenLegs
relay = RtoL
GOSUB sw1straight
DEBUG "sw1=S "
GOSUB accel
Direction=UP
DEBUG "Dir UP",10,13
ENDIF
IF reedsw2=Hit AND Direction=UP THEN
DEBUG "2 hit up",10,13
GOSUB ResetFlags:StopForMainLineFlag=1
GOSUB decel
GOSUB StopBetweenLegs
relay=LtoR
GOSUB sw1curved
DEBUG "sw1=C "
GOSUB sw2straight
DEBUG "sw2=S",10,13
GOSUB accel
ENDIF
IF reedsw3=Hit AND Direction=UP THEN
DEBUG "3 hit up",10,13
GOSUB ResetFlags
GOSUB decel
GOSUB StopBetweenLegs
relay=RtoL
GOSUB sw2curved
DEBUG "sw2=C "
GOSUB sw3straight
DEBUG "sw3=S",10,13
GOSUB accel
ENDIF
IF reedsw4=Hit AND direction=UP THEN
DEBUG "4 hit up",10,13
GOSUB ResetFlags
GOSUB decel
GOSUB StopBetweenLegs
relay=LtoR
GOSUB sw3curved
DEBUG "sw3=C",10,13
GOSUB accel
ENDIF
IF reedsw5=Hit THEN 'and direction=up then
DEBUG "5 hit up",10,13
GOSUB ResetFlags
GOSUB decel
GOSUB StopBetweenLegs
Direction=DOWN
DEBUG "Dir DOWN",10,13
relay=RtoL
GOSUB sw3curved
DEBUG "sw3=C",10,13
GOSUB accel
ENDIF
IF reedsw4=Hit AND direction=DOWN THEN
DEBUG "4 hit down",10,13
GOSUB ResetFlags
GOSUB decel
GOSUB StopBetweenLegs
relay=LtoR
GOSUB sw3straight
DEBUG "sw3=S "
GOSUB sw2curved
DEBUG "sw2=C",10,13
GOSUB accel
ENDIF
IF reedsw3=Hit AND direction=DOWN THEN
DEBUG "3 hit down",10,13
GOSUB ResetFlags:StopForMainLineFlag=1
GOSUB decel
GOSUB StopBetweenLegs
relay=RtoL
GOSUB sw2straight
DEBUG "sw2=S "
GOSUB sw1curved
DEBUG "sw1=C",10,13
GOSUB accel
ENDIF
IF reedsw2=Hit AND direction=DOWN THEN
DEBUG "2 hit down",10,13
GOSUB ResetFlags
GOSUB decel
GOSUB StopBetweenLegs
relay=LtoR
GOSUB sw1straight
DEBUG "sw1=S",10,13
GOSUB accel
ENDIF
GOTO WaitForReed:
speedup:
StoppedTrain=0
IF speed > 250 THEN start0:
speed=speed+2
WRITE 0, speed
GOTO dospeed:
speeddown:
IF speed < 5 THEN start0:
speed=speed -2
WRITE 0, speed
dospeed:
HPWM TIP101, speed, PWMFreq
DEBUG 13,10,"Speed= ",#speed
WRITE 0, speed
GOTO start01:
relayon:
IF direction =1 THEN
DEBUG "error",10,13
GOTO start01: 'if already going backward skip
ENDIF
GOTO dorelay:
relayoff:
IF direction=0 THEN
DEBUG "error",10,13
GOTO start01: 'if already going forward skip
ENDIF
dorelay:
GOSUB Decel
TOGGLE relay
GOSUB Accel:
direction=NOT(direction)
GOTO start01:
IncreaseStopTime:
IF stoptime < 98 THEN
StopTime=StopTime + 1
' high relaypolarity:pause 50:low relaypolarity
GOSUB ShowStopTime
WRITE 3, stoptime
ENDIF
GOTO start01:
DecreaseStopTime:
IF stoptime > 1 THEN
StopTime=StopTime - 1
' high relaypolarity:pause 50:low relaypolarity
GOSUB ShowStopTime
WRITE 3, stoptime
ENDIF
GOTO start01:
Decel:
DEBUG 13,10,"D-Speed= ",#speed, " "
FOR Temp=speed TO 0 STEP -5'changed to stop locos more rapidly 4-13-10 -adrate
HPWM TIP101, Temp, PWMFreq
'debug "."
temp1=255-speed: temp1=temp/20 'adjusts ad rate for low top speed
PAUSE temp1
NEXT Temp
HPWM TIP101,0,0:LOW TIP101
DEBUG 10,13
RETURN
Accel:
DEBUG 13,10,"A-Speed= ",#speed," "
FOR Tempword3=10 TO speed STEP adrate
HPWM TIP101, tempword3,PWMFreq
'debug "."
temp1=255-speed: temp1=temp1/10 'adjusts ad rate for low top speed
PAUSE temp1
NEXT Tempword3
HPWM TIP101, speed,PWMFreq
DEBUG "p 1.5 sec", 10,13
PAUSE 800 ' allow the train to pass the reed switch on its way out
DEBUG "p DONE!", 10,13
RETURN
StopBetweenLegs:
GOSUB ShowStopTime
FOR temp= 1 TO stoptime
DEBUG #temp," "
FOR temp2=1 TO 4
TOGGLE blueled
GOSUB getir 'problem if remote command seen here!
IF command <>0 THEN start02: 'exit on IR command
NEXT temp2
NEXT temp
DEBUG 10,13
RETURN
GetIR:
Getstartbits:
PULSIN IRin ,0,IRpulse_length(0)
IF IRpulse_length(0) < 400 THEN
'goto getstartbits
RETURN
ENDIF
FOR xx=1 TO 12
PULSIN IRin,0,IRpulse_length(xx)
NEXT xx
displaybits:
IF IRpulse_length(1) < 200 THEN
Command.Bit0=0
ELSE
Command.Bit0=1
ENDIF
IF IRpulse_length(2) < 200 THEN
Command.Bit1=0
ELSE
Command.Bit1=1
ENDIF
IF IRpulse_length(3) < 200 THEN
Command.Bit2=0
ELSE
Command.Bit2=1
ENDIF
IF IRpulse_length(4) < 200 THEN
Command.Bit3=0
ELSE
Command.Bit3=1
ENDIF
IF IRpulse_length(5) < 200 THEN
Command.Bit4=0
ELSE
Command.Bit4=1
ENDIF
IF IRpulse_length(6) < 200 THEN
Command.Bit5=0
ELSE
Command.Bit5=1
ENDIF
IF IRpulse_length(7) < 200 THEN
Command.Bit6=0
ELSE
Command.Bit6=1
ENDIF
IF IRpulse_length(8) < 200 THEN
Command.Bit7=0
ELSE
Command.Bit7=1
ENDIF
IF Command.Bit7=0 THEN 'Bit 7 is one of the device bits
Command=Command + 1
ENDIF
IF Command=10 THEN
Command=0
ENDIF
DEBUG "code= ", #command ,13,10
'serout serial_out,n9600,[13,10,"command", #command," speed ", #speed," PauseByte ", #PauseByte, 13,10]
RETURN
GetDigits:
DEBUG 10,13, "@G Digits", 10,13
HPWM TIP101, 0, 0 'all stop
digit=2
command=0
DigitsByte=0
HIGH BlueLED:PAUSE 1000:LOW BlueLED
GetDigits0:
GOSUB GetIR:
IF command=0 THEN GetDigits0
IF command > 137 OR command < 128 AND command <>139 AND command <> 0 THEN
GOTO VeryTop: 'abort on non number 0-9
ENDIF
IF command=139 THEN GetDigits0:
Value=command-127
IF Value=10 THEN value=0
IF value=0 THEN HIGH BlueLED:PAUSE 500:LOW BlueLED
FOR tempbyte=1 TO value:HIGH BlueLED:PAUSE 200:LOW BlueLED:PAUSE 200:NEXT tempbyte
DigitsByte=DigitsByte*10+Value
digit=digit-1
PAUSE 200:command=0
IF digitsbyte > 255 THEN digitsbyte=255
IF digit=0 THEN
StopTime =digitsbyte
WRITE 3,stoptime
' write 4, stoptime-temp*256
GOSUB ShowStopTime:DEBUG " ",#temp," ",#stoptime-temp*256,10,13
' speed=DigitsByte
GOTO Start0: 'StartReverse:
ENDIF
GOTO GetDigits0:
AllRelaysOff:
LOW ServoSW3:LOW ServoSW2:LOW ServoSW1 ':low RelayPolarity:
RETURN
SW1curved:
DEBUG,"1=S " ,#direction ,10,13
FOR Temp=CW1 TO CCW1 STEP 1
PULSOUT servosw1, temp
TOGGLE blueled
PAUSE Delay
NEXT Temp
RETURN
SW1straight:
DEBUG,"1=S " ,#direction ,10,13
FOR Temp=CCW1 TO CW1 STEP -1
PULSOUT servosw1, temp
HIGH blueled
PAUSE Delay
NEXT Temp
RETURN
SW2Curved:
DEBUG,"2=C ",#direction ,10,13
FOR Temp=CW2 TO CCW2 STEP 1
PULSOUT servosw2, temp
TOGGLE blueled
PAUSE Delay
NEXT Temp
RETURN
SW2Straight:
DEBUG,"2=S " ,#direction ,10,13
FOR Temp=CCW2 TO CW2 STEP -1
PULSOUT servosw2, temp
HIGH blueled
PAUSE Delay
NEXT Temp
RETURN
SW3Straight:
DEBUG,"3=S " ,#direction ,10,13
FOR Temp=CW3 TO CCW3 STEP 1
PULSOUT servosw3, temp
HIGH blueled
PAUSE Delay
NEXT Temp
RETURN
SW3Curved:
DEBUG,"3=C " ,#direction ,10,13
FOR Temp=CCW3 TO CW3 STEP -1
PULSOUT servosw3, temp
TOGGLE blueled
PAUSE Delay
NEXT Temp
RETURN
ResetFlags:
StopForMainLineFlag = 0:ReedSWX6HitFlag =0:ReedSWX7HitFlag =0:RETURN
ShowStopTime:
DEBUG "STime= ",#stoptime,10,13:RETURN
|