hArduino-1.0: System/Hardware/Arduino/SamplePrograms/Servo.hs
-------------------------------------------------------------------------------
-- |
-- 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 (<http://www.servocity.com/html/hs-55_sub-micro.html>), 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:
--
-- <<http://github.com/LeventErkok/hArduino/raw/master/System/Hardware/Arduino/SamplePrograms/Schematics/Servo.png>>
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:
--
-- <<http://github.com/LeventErkok/hArduino/raw/master/System/Hardware/Arduino/SamplePrograms/Schematics/ServoAnalog.png>>
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