------------------------------------------------------------------------------- -- | -- Module : System.Hardware.Arduino.SamplePrograms.Distance -- Copyright : (c) Levent Erkok -- License : BSD3 -- Maintainer : erkokl@gmail.com -- Stability : experimental -- -- Measuring distance using a HC-SR04 sensor. (Data sheet: .) -- -- NB. As of March 2 2013; StandardFirmata that's distributed with the Arduino-App does /not/ support the high -- accuracy pulse-in command, which is needed for this sketch. However, there is a patch to add this -- command; see: for details on how to install it. You /should/ -- have this patched version of Firmata running on your board for this sketch to function properly. -- -- Accuracy: Keep in mind that measurements on a platform like Arduino is always subject to -- various errors. Relying on this program for precise distance measurements would be a mistake. -- The results here should be accurate to within about half-a-centimeter, provided you stay -- within the range of HC-SR04, which is between 2 to 400 cm. For anything more precise than -- this, you'll need to use a much more sensitive sensor. ------------------------------------------------------------------------------- module System.Hardware.Arduino.SamplePrograms.Distance where import Control.Monad (forever) import Control.Monad.Trans (liftIO) import Numeric (showGFloat) import System.Hardware.Arduino -- | Sound travels 343.2 meters per seconds (). -- The echo time is round-trip, from the sensor to the object and back. Thus, if echo is high -- for @d@ microseconds, then the distance in centimeters is: -- -- @ -- d * 10^-6 * 343.2 * 10^2 / 2 -- = 1.716e-2 * d -- @ microSecondsToCentimeters :: Int -> Float microSecondsToCentimeters d = 1.716e-2 * fromIntegral d -- | Measure and display the distance continuously, as reported by an HC-SR04 sensor. -- -- Wiring: Simply connect VCC and GND of HC-SR04 to Arduino as usual. The @Echo@ line on the sensor is connected -- to Arduino pin 2. The @Trig@ line is connected on the board to the @Echo@ line, i.e., they both connect to the -- same pin on the Arduino. We also have a led on pin 13 that we will light-up -- if the distance detected is less than 5 centimeters, indicating an impending crash! -- -- <> distance :: IO () distance = withArduino False "/dev/cu.usbmodemfd131" $ do setPinMode sensor INPUT setPinMode led OUTPUT update where sensor = digital 2 led = digital 13 measure = do mbd <- pulse sensor True 10 Nothing case mbd of Nothing -> liftIO $ putStrLn "Distance: No measurement received." Just d -> do let c = microSecondsToCentimeters d liftIO $ putStrLn $ "Distance: " ++ showGFloat (Just 2) c " centimeters." digitalWrite led (c < 5) update = forever $ do measure delay 1000