Wednesday, January 6, 2010

Code for BS2 BOE

' {$STAMP BS2}
' {$PBASIC 2.5}
' Dump4everV3.bs2 as of 2009dec14
' Written for an Education Board: 4 Servos are hard wired to pins 12-15
' V1 started in 2009November
' V2 Changed Positioner code to try to get the push bar to place car OVER brake
' V3 Changed Pusher bar to a Coupler Grabber

' Controls four servos of an automated HO scale rotary dumper
' 1. Dumper motor is a Parallax Futaba limitless servo.
' It has a PULSOUT dead band (758..761 x2usec) 1515..1522.
' Values near the deadband control the speed that reachs a maximum
' of about 60RPM at PULSOUT values of about +/-40. 1 RevPerSecond.
' The travel limits are controlled with a single flapper switch
' flapped at 2 positions Reverse and StopatTop
' 2. Positioner motor is a Parallax Futaba limitless servo.
' It has a PULSOUT dead band (756 TO 760 x2usec) 1512 to 1520 .
' 'ditto' has 2 flapper switches :PositionerAtEnd and PositionerBack
' 3. Positioner Arm motor is a Parallax Futaba servo.
' It rides on the Positioner cart and raises - lowers its arm
' to be the positioner car coupler grabber
' 4. Brake is an old Futaba servo.
' It is under the track and raises its arm
' to hold the car in the correct position.

' The red green LEDs will be flashing when system is powered up
' and a reset cycle has been done. It will flash idiot lights
' when the system is waiting for a train

'After Initialization-Power on - the cars are placed in position
' Three Buttons on a Servo extension in a bashed Coalgon
StartButton PIN 0 'white-yel wire
'Just in case
EmergencyStopBtn PIN 1 'red wire
'Used when done to dump last car(s) pulled onto dumper by other loco
RotateDumper1Btn PIN 2 'black wire

'Flapper switches for servo movement limits
'Positioner limits
PositionerAtEnd PIN 3 'black wire Positioner Near Dumper
'A B hehehe - this will haunt me right ?
PositionerBack PIN 4 'red wire Positioner at back
'1 switch-sensor used to Reverse and Stop at Top Dumper
DumperSensor PIN 5 ' white wire
'Photo diode light detector
CheckLight PIN 6 'its own wire set
'not really coded - just flashing lights
GreenLight PIN 7 'yel-white wire
'No error detection AFAIK so just for funsies
RedLight PIN 8 'red wire , black of set is ground
Siren PIN 9 'on board only- sounds at end of cycle
'IR detector for a hand held TV remote control IAW Three Buttons
'PIN 10
'o what to do with these, i just gotta use it all :)
'Additional Servo Positioner Retract servo-
'but not needed if the Positioner actually Works ...
'used to Stop the incoming train cars at correct location
'PIN 11

'4 Servos on Pins: 12 :Positioner, 13: Arm, 14 : Brake, 15 : Dumper
dumperSpeed VAR Word
dumperSpeed=20 'Set here to change all places easier
dumperStop VAR Word
dumperStop=760 'center of dead band
positionerSpeed VAR Word
positionerSpeed=20 'Set here to change all places easier
positionerStop VAR Word
positionerStop=758 'center of dead band
brakeSet VAR Word
brakeSet=570 '582 '583 'Brake holds the axle Tight

'THE PLOT
'A Unit train arrives and the Power de-couples from front
' and runs around dumper to wait for its train to be dumped.
' The train is Pushed to Positioner by Industry Power.
'The Positioner is near dumper, Arm and the Brake are Down.
'the Start Button is Pressed
'Position1Car: Push 1 car forward and Brake it,
'Check if more cars (Light detector) {it is needed here the first time...}
'then go into the lOOP
'lOOP:
'Push 1 car forward and Brake it, the car before is Now in dumper
'Rotate Dumper
'Check if more cars (Light detector )
'Repeat LOOP until Detector Exits the Loop : no more cars
'Done: Retract brake and raise Positioner a LITTLE bit
' as it has GRABBED the Coupler
' Positioner Near Dumper and the Arm raised a LITTLE
'Thus at end 1 car on ready-track , 1 car On dumper : IS dumped
'Pull Last car through-onto Dumper from other end with Power locomotive.
' Then Dump Last car Using the 3rd Push button to activate Dumper

'global variables Byte : Value can be 0 to 255
counter VAR Word ' Value can be 0 to 65535
debugthis VAR Word
carShadow VAR Word
' >1600 is a car <50 is no car , THIS is middle low
carShadow=500
time VAR Word 'IF (time < CarShadow) THEN NoMoreCars=1
noMoreCars VAR Bit
duration VAR Word 'for Sound
frequency VAR Word 'ditto

'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////
'THE PROGRAM
'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////
DEBUG "Program started",CR 'Print to computer screen
DO 'Do a MAIN LOOP Responding to the 3 Buttons ...
'Initialize Something
'All pins are input at startup, PULSOUT takes care of Output by itself
'the photo resistor will be High 6 ONLY while running AFAIK

'Check Buttons at Start AND while Looping ...
GOSUB Check_Buttons

'Flash some LEDs GreenLight PIN 8 , RedLight PIN 9
PULSOUT 8,50000 'red
'go check buttons rather than pause to 'seem' interactive
GOSUB Check_Buttons 'PAUSE 100
PULSOUT 7,65000 '130msec ON Green LED
GOSUB Check_Buttons 'PAUSE 200 '200msec OFF
GOSUB Check_Buttons
PULSOUT 8,50000 'red
GOSUB Check_Buttons 'PAUSE 100
PULSOUT 7,65000 '130msec ON
GOSUB Check_Buttons 'PAUSE 200 '200msec OFF
GOSUB Check_Buttons
PULSOUT 8,50000 'red
GOSUB Check_Buttons 'PAUSE 100
PULSOUT 7,65000 '130msec ON Green LED
GOSUB Check_Buttons 'PAUSE 200 '200msec OFF
GOSUB Check_Buttons
PULSOUT 8,50000 'red
GOSUB Check_Buttons 'PAUSE 100
PULSOUT 7,65000 'four flashes ident this program version
GOSUB Check_Buttons 'PAUSE 200
GOSUB Check_Buttons
PULSOUT 8,50000 'red
GOSUB Check_Buttons 'PAUSE 100
'MAIN LOOP ENDS here
LOOP 'YES it will run Forever .. UNTIL Emergency STOP BUTTON is pressed
END 'so this end is redundant and never used, wasting program space
'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////
'The Program Ends
'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////

'/////////////////////////////////////////////////////
'Check_Buttons:
'/////////////////////////////////////////////////////
Check_Buttons:
FOR counter = 1 TO 50 'check a lot between the LEDs being ON
'Start and Run the Sequence .. StartDumpRun
IF (StartButton=1) THEN GOSUB Start_Dump_Run
'Emergency Stop
IF (EmergencyStopBtn=1) THEN END
'Dumper
IF (RotateDumper1Btn=1) THEN GOSUB Rotate_Dumper
NEXT
'IR TV control would be similar to 3 Buttons ... someday
RETURN 'return from a Gosub
'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////


'/////////////////////////////////////////////////////
'StartDumpRun Starts here
'/////////////////////////////////////////////////////
Start_Dump_Run :
DEBUG "Positioner started",CR
'Put 1 car ahead of Loop
GOSUB Position_1Car
IF (emergencyStopBtn=1) THEN END

'Check Light detector
GOSUB Traffic_Light
IF (noMoreCars=1) THEN END 'Something is Really wrong-or just testing
DEBUG "Lets dump this Unit Train!",CR
DEBUG "till the Light is less than the Shadow",CR
DO
'BE SURE TO Watch for the Emergency Stop Button! During the Sequence
IF (emergencyStopBtn=1) THEN END

DEBUG "Positioner started",CR
GOSUB Position_1Car
IF (emergencyStopBtn=1) THEN END

'Could maybe use a light detector at Edge of dumper to check for
'correct placement- but setting it up so no false reads seems Difficult-
'It would depend on where the light is from
' as the detector would be at edge of car.

DEBUG "Rotating Dumper",CR
GOSUB Rotate_Dumper
IF (emergencyStopBtn=1) THEN END

GOSUB Traffic_Light
IF (noMoreCars=1) THEN EXIT 'See Light at end of tunnel
LOOP

DEBUG "All done! use Locomotive for positioning",CR
DEBUG "Dumper Control with the Dumper button",CR
'Raise arm a LITTLE bit to release Coupler so Power can move the cars
FOR counter= 932 TO 789 STEP 10 'gradual raise arm a LITTLE bit
PULSOUT 13, counter 'hope they dont roll away...
PAUSE 20 'o they cant-arm is on this side
NEXT 'Power is at the Front of train again
GOSUB Lower_Brake
GOSUB Hyperspaced 'If i knew music i would play a tune
RETURN 'or cared to play a cellphone ringtone
'/////////////////////////////////////////////////////
'Start_Dump_Run ENDS here
'/////////////////////////////////////////////////////

'/////////////////////////////////////////////////////
'Hyperspaced: notification of completion
'/////////////////////////////////////////////////////
Hyperspaced:
PAUSE 100
FOR duration = 15 TO 1 'STEP 1 Step 1 is Normal? change
FOR frequency = 2000 TO 2500 STEP 20
FREQOUT 9, duration, frequency
NEXT
NEXT
FREQOUT 9, 2000, 2000, 2010
RETURN
'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////


'/////////////////////////////////////////////////////
'Traffic_Light:
'/////////////////////////////////////////////////////
' HIGH 6 is same as OUT6 = 1 and DIR6 = 1
' Make the specified pin an output and high.
' The HIGH command sets the specified pin to 1 (a +5 volt level)
' and then sets its mode to output.
' LOW 6 OUT6 = 0 DIR6 = 1
' The LOW command sets the specified pin to 0 (a 0 volt level)
' and then sets its mode to output.
'/////////////////////////////////////////////////////
Traffic_Light:
HIGH 6 ' CheckLight PIN 6
PAUSE 100 'charge capacitor
RCTIME 6, 1, time
IF (time < carShadow) THEN noMoreCars=1
'DEBUG HOME, "time = ", DEC5 time," CarShadow = ",DEC5 CarShadow
DEBUG "Light ", DEC5 time," < ",DEC5 carShadow, " Shadow?", CR
'carShadow = 500 '>1600 is a car <50 is no car
'Dark is big, Light is small time values
LOW 6 ' i dunno if i should,
'but i dont want current charging all the time
RETURN
'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////


'/////////////////////////////////////////////////////
'Position_1Car
'/////////////////////////////////////////////////////
'Brake should be Set, Arm Down
'Positioner Arm values
' 900 all UP, 1500 Car top, 1800 above coupler, 1830 grabs coupler
' 1840 ehh, 1850 ehehe, 1855 good little loose, 1860 ! little loose
' 1865 ok, 1870 tight, 1873 too Tight, 1880 Servo grumbling
'932=1864 1864=932=466
'/////////////////////////////////////////////////////
Position_1Car:
'Check-Set brake just in case, Raise Arm, Move Positioner to Back,
PULSOUT 14, brakeSet
PAUSE 20

'Raise arm SLOWLY ? to clear cars
FOR counter= 932 TO 466 STEP 10 'gradual raise arm
PULSOUT 13, counter
PAUSE 20
NEXT
PULSOUT 13, 466 '13: Arm 'dunno what step does to leftovers
PAUSE 20
'DIR13=0 'remove pulse to insure stop
IF (emergencyStopBtn=1) THEN END

FOR counter = 1 TO 5 'Move it back past the switch
PULSOUT 12, positionerStop-positionerSpeed
PAUSE 20
NEXT
debugthis=0 '12 :Positioner - is CW is Reverse
DO
debugthis=debugthis+1
PULSOUT 12, positionerStop-positionerSpeed
PAUSE 20
LOOP WHILE (PositionerBack=0) 'away from dumper
PULSOUT 12, positionerStop
PAUSE 20
'DIR12=0 'remove pulse to insure stop
DEBUG "Positioner Reverse: ", DEC debugthis, CR
IF (EmergencyStopBtn=1) THEN END

'Lower Arm to Grab Coupler and push, Lower Brake so cars can move
FOR Counter= 466 TO 888 STEP 5'10 'gradual Lower arm
PULSOUT 13, Counter
PAUSE 20
NEXT
FOR Counter= 888 TO 932 'Very gradually Lower arm to Coupler bar
PULSOUT 13, Counter
PAUSE 20
NEXT
PULSOUT 13, 932 '13: Arm
PAUSE 20
' DIR13=0 'remove pulse to insure stop
IF (emergencyStopBtn=1) THEN END

GOSUB Lower_Brake 'so cars can move forward
IF (emergencyStopBtn=1) THEN END

'Move Positioner forward, Set Brake
debugthis=0 '12 :Positioner + is CCW is Forward
FOR counter = 1 TO 5 'Move it past the switch
PULSOUT 12, positionerStop+positionerSpeed
PAUSE 20
NEXT
DO
debugthis=debugthis+1
PULSOUT 12, positionerStop+positionerSpeed
PAUSE 20
LOOP WHILE (PositionerAtEnd=0) 'PositionerAtEnd
PULSOUT 12, positionerStop
PAUSE 20
' DIR12=0 'remove pulse to insure stop
DEBUG "Positioner Forward: ", DEC debugthis, CR
IF (EmergencyStopBtn=1) THEN END

GOSUB Set_Brake
RETURN
'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////


'/////////////////////////////////////////////////////
'Set_Brake:
'/////////////////////////////////////////////////////
'Brake ups and downs
'1000 is Topped OUT : 500 : it hits the track above
'1050 is just clear of Top Out : 525
'1130 '1161 it Lifts the wheels from the track 580 or 581 582
'1136 ...1140 is Good and Tight
'1140 : 570 '1164 : brakeSet=582
'1145 '1166 BrakeSet is just before : 583
'1150 ...is caught but...
'1200 is caught but way loose 600
'1500 is Below track : 750 normal centered
'1800 is bottom out:900
'/////////////////////////////////////////////////////
Set_Brake:
'debug "Set Brake"
FOR Counter= 750 TO brakeSet STEP 4 '10 gradual brake-raise arm to axle
PULSOUT 14, Counter '14 : Brake
PAUSE 20
NEXT
PULSOUT 14, brakeSet 'dunno what step does to leftovers
PAUSE 20
' DIR14=0 'remove pulse to insure stop
'debug "Brake Set"
RETURN ' from Sub SetBrake:

Lower_Brake:
'debug "Lower Brake"
FOR counter=brakeSet TO 750 STEP 10 'gradual release -- going down
PULSOUT 14, counter '14 : Brake
PAUSE 20
NEXT
PULSOUT 14, 750
PAUSE 20
' DIR14=0 'remove pulse to insure stop
'debug "Brake Lowered"
RETURN ' from Sub LowerBrake:
'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////


'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////
'RotateDumper
'/////////////////////////////////////////////////////
'Set Dumper to rotating (its Not a Position, it is the rotation Speed
'Check Switch-Sensor and Reverse when it is hit
'till it is hit again at top and Stopped

Rotate_Dumper: '15 : Dumper
DEBUG "Dumper started", CR
debugthis=5
FOR counter = 1 TO 5 'Move it past the switch - then keep going
PULSOUT 15, dumperStop+dumperSpeed ' + is CCW is Forward to Dump
PAUSE 20
'DEBUG "Dumper ",DEC DumperSensor ,CR 'used during actual de-bugging once
NEXT

'The servo IS turning till Switch hit
DO 'DO:LOOP WHILE(?=0) is a trick
debugthis=debugthis+1
PULSOUT 15, dumperStop+dumperSpeed ' + is CCW is Forward to Dump
PAUSE 20
LOOP WHILE (DumperSensor=0)
PULSOUT 15, dumperStop 'Stop turning, so it does not spit gears reversing
PAUSE 20
IF (emergencyStopBtn=1) THEN END
DEBUG "Dumper Upsidedown: ", DEC debugthis, CR

DEBUG "Dumper returning", CR
debugthis=5
FOR counter = 1 TO 5 'Move it past the switch
PULSOUT 15, dumperStop-dumperSpeed ' - is CW is Reverse to TOP
PAUSE 20
NEXT

'The servo IS turning till Switch hit
DO
debugthis=debugthis+1
PULSOUT 15, dumperStop-dumperSpeed ' - is CW is Reverse to TOP
PAUSE 20
LOOP WHILE (DumperSensor=0)
PULSOUT 15, dumperStop 'Stop turning, we are at top again
PAUSE 20
' DIR15=0 'remove pulse to insure stop
IF (emergencyStopBtn=1) THEN END
DEBUG "Dumper Topside: ", DEC debugthis, CR 'to count turnaround loops
DEBUG "Dumper Done", CR 'totally useless but interesting
RETURN
'/////////////////////////////////////////////////////
'/////////////////////////////////////////////////////


'/////////////////////////////////////////////////////
'NO MORE CODE :)
'/////////////////////////////////////////////////////
END 'just in double case, yes some more wasted code space :)

No comments:

Post a Comment