------------------------------------------------------------------------------- -- | -- Module : System.Hardware.Arduino.SamplePrograms.Servo -- Copyright : (c) Levent Erkok -- License : BSD3 -- Maintainer : erkokl@gmail.com -- Stability : experimental -- -- Demonstrates basic Servo motor control ------------------------------------------------------------------------------- module System.Hardware.Arduino.SamplePrograms.Servo where import Control.Monad (forever) import Control.Monad.Trans (liftIO) import Data.Char (toLower) import System.Hardware.Arduino import System.Hardware.Arduino.Parts.Servo -- | Control a servo, by executing user requests of blade movement. We allow 3 user commands: -- -- * @l@ to swipe from angle-0 to 180; -- -- * @r@ to swipe from angle-180 to 0; -- -- * Or any number between @0@ to @180@, which puts the servo to the desired position. -- -- Almost any servo motor would work with this example, though you should make sure to adjust min/max pulse durations -- in the 'attach' command to match the datasheet of the servo you have. In this example, we have used the HS-55 feather -- servo (), which has the values 600 to 2400 micro-seconds. -- -- To connect the servo to the Arduino, simply connect the VCC (red) and the GND (black) appropriately, and the signal line (white) -- to any SERVO capable pin, in this example we're using pin number 9: -- -- <> servo :: IO () servo = withArduino False "/dev/cu.usbmodemfd131" $ do s <- attach (digital 9) (Just 600) (Just 2400) forever (demo s) where demo s = do liftIO $ putStr "Enter l, r or the desired servo angle: " a <- liftIO getLine case (map toLower a, reads a) of ("l", _) -> mapM_ move [0 .. 180] ("r", _) -> mapM_ move [180, 179 .. 0] (_, [(v, "")]) | 0 <= v && v <= 180 -> setAngle s v _ -> liftIO $ putStrLn "Invalid entry." where move a = setAngle s a >> delay 100 -- | Control a servo, as guided by the input read from a potentiometer. The set-up is similar to the 'servo' example -- above, except instead of querying the user for the angle, we use the readings from a potentiometer connected to -- analog input number 2. We used a 10 KOhm potentiometer, but other pots would work just as well too: -- -- <> servoAnalog :: IO () servoAnalog = withArduino False "/dev/cu.usbmodemfd131" $ do s <- attach (digital 9) (Just 600) (Just 2400) setPinMode pot ANALOG liftIO $ putStrLn "Adjust the potentiometer to control the servo!" forever (demo s) where pot = analog 2 demo s = do v <- analogRead pot setAngle s (cvt v) delay 100 -- Analog input will be from 0 to 1023; convert it to -- angles, mapping 1023 to 0-degrees, and 0 to 180 cvt i = ((1023-i) * 180) `div` 1023