{- A simple line-following robot. - - This is not the most efficient or best way to implement it - (it compiles to around 500 lines of C code), but - it is a good example of building up a Sketch by combining - simpler Sketches. -} {-# LANGUAGE RebindableSyntax #-} module Examples.Robot.Demo where import Copilot.Arduino.Uno import qualified Copilot.Arduino.Library.Serial.XBee as XBee main :: IO () main = arduino $ do XBee.configure pin2 pin3 (XBee.Baud 9600) emergencystop <- input pin4 if emergencystop then stop else do ll <- leftLineSensed rl <- rightLineSensed if ll && rl then stop else if ll then turnLeft else if rl then turnRight else goForward stop :: Sketch () stop = do led =: true XBee.device =: [XBee.str "stopped\n"] rightWheelMotor true (constant 0) leftWheelMotor true (constant 0) goForward :: Sketch () goForward = do led =: false XBee.device =: [XBee.str "forward\n"] leftWheelMotor true (constant 255) rightWheelMotor true (constant 255) turnLeft :: Sketch () turnLeft = do led =: blinking XBee.device =: [XBee.str "turn left\n"] rightWheelMotor true (constant 128) leftWheelMotor false (constant 128) turnRight :: Sketch () turnRight = do led =: blinking XBee.device =: [XBee.str "turn right\n"] rightWheelMotor false (constant 128) leftWheelMotor true (constant 128) leftLineSensed :: Sketch (Behavior Bool) leftLineSensed = lineSensed a1 "left" rightLineSensed :: Sketch (Behavior Bool) rightLineSensed = lineSensed a2 "right" lineSensed :: IsAnalogInputPin t => Pin t -> [Char] -> Sketch (Stream Bool) lineSensed pin desc = do v <- input pin :: Sketch (Behavior ADC) XBee.device =: [ XBee.str (desc <> " line sensor:") , XBee.show v , XBee.char '\n' ] return (v > 50) leftWheelMotor :: Behavior Bool -> Behavior Word8 -> Sketch () leftWheelMotor = wheelMotor pin5 pin6 rightWheelMotor :: Behavior Bool -> Behavior Word8 -> Sketch () rightWheelMotor = wheelMotor pin9 pin10 wheelMotor :: (IsPWMPin t1, IsPWMPin t2) => Pin t1 -- ^ pin to drive motor forward -> Pin t2 -- ^ pin to drive motor backward -> Behavior Bool -- ^ True when driving forward -> Behavior Word8 -- ^ How hard to drive the motor. -> Sketch () wheelMotor forwardpin backwardpin forward power = do forwardpin =: pwm (if forward then power else constant 0) backwardpin =: pwm (if forward then constant 0 else power)