'{$STAMP BS2p} '{$PBASIC 2.5} ACMotorUp pin 0 ACMotorDown pin 1 DCMotorPin pin 15 SwitchBack pin 11 'red/white cable SwitchFront pin 12 'green/white cable IrDetector pin 13 ObjectDetectorIn pin 7 ObjectDetectorVoltage pin 10 'AC motor cables: ' red cable: AC ground ' green cable: common AC line ' blue cables: AC line: ' yellow stripe: motor up ' white stripe: motor down 'gosub DoStopDCMotor 'gosub DoStopACMotor 'end '--------------- 'State variables '--------------- 'Current state of the system ' bit0 ' bit1 - horizontal arm, the DC motor. If 1 the motor is moving, ' with the direction given by the value of Action ' bit2 - vertical screen, powered by the AC motor. If 1, the motor ' is moving, with the direction given by the value of Action ' bit 3 'The initial value of this variable is 1 SystemState var byte 'The last value of SystemState when the motors executed something. 'Initial value is the same as SystemState. LastSystemState var byte 'SystemState gets saved here when we press the Stop button on the remote 'Initial value is 0 SavedSystemState var byte 'Action to take ' 0: none ' 1: stop ' 2: drop screen ' 3: retract screen Action var byte LastAction var byte SavedAction var byte 'Timer used to count the time since a high level command was started. 'Each operation that we execute has a time limit in which it has to 'finish. The timer is incremented in the main loop, but reset each 'time a motor starts moving. Timer var word '--------------- 'Infrared remote control constants. '--------------- IrThresholdStart con 2700 IrThresholdPulse con 1200 'IR commands for a Sony TV IrEnter con 11 IrChannelUp con 16 IrChannelDown con 17 IrVolumeUp con 18 IrVolumeDown con 19 IrMute con 20 IrPower con 21 IrSleep con 54 IrLast con 59 IrMenu con 96 '--------------- 'Infrared detector variables IrRemoteCode var byte '--------------- 'Various constants '--------------- MotorSerialSpeed con 1021 MotorForward con 127 MotorBackward con -127 ActionNone con 0 ActionStop con 1 ActionExtendScreen con 2 ActionRetractScreen con 3 'How long in miliseconds is the AC motor allowed to run 'We run slightly longer when we retract the screen, to 'make sure it retracts entirely. MaxACMotorExtendRunTime con 14500 MaxACMotorRetractRunTime con MaxACMotorExtendRunTime + 1000 'How long to pause for in the main loop PauseTime con 100 '--------------- 'Temporary variables '--------------- irPulse var word i var byte newAction var byte ignoreFewVerticalSwitches var byte '--------------- debug CLS, "Press CH+, CH- or Power on the remote, 5 is panic...", cr MainLoop: 'Reset the state Action = ActionNone LastAction = Action SavedAction = Action SystemState = 1 LastSystemState = SystemState SavedSystemState = 0 gosub DoStopMotors do 'If we are either fully extended or retracted, we can afford to pause 'to minimize power consumption on the BS2p. if SystemState & $00000110 = 0 then pause PauseTime endif newAction = ActionNone 'Read the IR detector pulsin IrDetector, 0, irPulse if irPulse > IrThresholdStart then gosub Get_Ir_Remote_Code debug "Got IR code ", ? IrRemoteCode select IrRemoteCode case IrPower newAction = ActionStop case IrChannelDown newAction = ActionExtendScreen case IrChannelUp newAction = ActionRetractScreen case 5 gosub HandlePanicButton goto MainLoop case IrLast gosub DumpState endselect debug "code = ", dec IrRemoteCode, cr if newAction <> ActionNone and newAction <> Action then LastAction = Action debug "prev ", ? Action Action = newAction debug "now ", ? Action endif endif if SystemState.bit2 then Timer = Timer + PauseTime 'If we've pressed Up or Down and we're restarting 'a previously stopped action, restore the saved state if Action > ActionStop and SavedSystemState <> 0 then debug "restoring from saved state", cr SystemState = SavedSystemState SavedSystemState = 0 if SavedAction <> Action then debug "resetting timer...", cr Timer = 0 endif elseif Action = ActionExtendScreen then if (SystemState.bit0 = 1 or (SystemState.bit1 = 1 and SwitchFront = 0) or (SystemState.bit2 = 1 and (Timer > MaxACMotorExtendRunTime or ObjectDetectorIn = 0))) then if SystemState < 8 then SystemState = SystemState << 1 debug "incremented ", ? SystemState Timer = 0 endif endif elseif Action = ActionRetractScreen then if (SystemState.bit3 = 1 or (SystemState.bit1 = 1 and SwitchBack = 0) or (SystemState.bit2 = 1 and (Timer > MaxACMotorRetractRunTime or ObjectDetectorIn = 0))) then if SystemState > 1 then debug "decremented ", ? SystemState SystemState = SystemState >> 1 Timer = 0 endif if SystemState.bit2 = 1 then ignoreFewVerticalSwitches = 1 endif endif elseif Action = ActionStop and SavedSystemState = 0 then debug "saving state...", cr SavedSystemState = SystemState SavedAction = LastAction SystemState = 0 'Reset the action to prevent it entering this branch next time around Action = ActionNone endif gosub HandleDCMotor gosub HandleACMotor if ignoreFewVerticalSwitches = 1 then pause 300 ignoreFewVerticalSwitches = 0 endif LastSystemState = SystemState loop HandleDCMotor: if SystemState.bit1 <> LastSystemState.bit1 then if SystemState.bit1 = 1 then if Action = ActionRetractScreen then debug "retracting horizontal arm...", cr serout DCMotorPin, MotorSerialSpeed, [$55, $08, MotorBackward] elseif Action = ActionExtendScreen then debug "extending horizontal arm...", cr serout DCMotorPin, MotorSerialSpeed, [$55, $08, MotorForward] endif else debug "stopping DC motor...", cr serout DCMotorPin, MotorSerialSpeed, [$55, $00] endif endif return HandleACMotor: if SystemState.bit2 <> LastSystemState.bit2 then if SystemState.bit2 = 1 then if Action = ActionRetractScreen then debug "retracting screen...", cr low ACMotorDown pause 100 high ACMotorUp high ObjectDetectorVoltage elseif Action = ActionExtendScreen and SwitchFront = 0 then debug "extending screen...", cr low ACMotorUp pause 100 high ACMotorDown high ObjectDetectorVoltage endif else debug "stopping AC motor...", cr low ACMotorDown low ACMotorUp low ObjectDetectorVoltage endif endif return DoStopMotors: serout DCMotorPin, MotorSerialSpeed, [$55, $00] low ACMotorUp low ACMotorDown return HandlePanicButton: debug "Panic, resetting!", cr gosub DoStopMotors high AcMotorUp pause MaxACMotorRetractRunTime + 3000 low AcMotorUp serout DCMotorPin, MotorSerialSpeed, [$55, $08, MotorBackward] do while SwitchBack <> 0 pause 100 loop debug "Panic stopped!", cr return 'Call this function from main loop when input has been received on IrDetector, 'e.g. when IrPulse > IrThresholdStart Get_Ir_Remote_Code: IrRemoteCode = 0 pulsin IrDetector, 0, irPulse if irPulse > IrThresholdPulse then IrRemoteCode.bit0 = 1 pulsin IrDetector, 0, irPulse if irPulse > IrThresholdPulse then IrRemoteCode.bit1 = 1 pulsin IrDetector, 0, irPulse if irPulse > IrThresholdPulse then IrRemoteCode.bit2 = 1 pulsin IrDetector, 0, irPulse if irPulse > IrThresholdPulse then IrRemoteCode.bit3 = 1 pulsin IrDetector, 0, irPulse if irPulse > IrThresholdPulse then IrRemoteCode.bit4 = 1 pulsin IrDetector, 0, irPulse if irPulse > IrThresholdPulse then IrRemoteCode.bit5 = 1 pulsin IrDetector, 0, irPulse if irPulse > IrThresholdPulse then IrRemoteCode.bit6 = 1 if IrRemoteCode < 10 then IrRemoteCode = IrRemoteCode + 1 if IrRemoteCode = 10 then IrRemoteCode = 0 return DumpState: debug ? Action debug ? SystemState debug ? LastSystemState debug ? LastAction debug ? SavedSystemState debug ? Timer return