--------------------------------------------------------------------------------- |-- 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: <http://www.micropik.com/PDF/HCSR04.pdf>.)---- 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: <http://github.com/rwldrn/johnny-five/issues/18> 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.-------------------------------------------------------------------------------moduleSystem.Hardware.Arduino.SamplePrograms.DistancewhereimportControl.Monad(forever)importControl.Monad.Trans(liftIO)importNumeric(showGFloat)importSystem.Hardware.Arduino -- | Sound travels 343.2 meters per second (<http://en.wikipedia.org/wiki/Speed_of_sound>).-- 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->FloatmicroSecondsToCentimeters :: Int -> Float microSecondsToCentimeters Int d =Float 1.716e-2forall a. Num a => a -> a -> a *forall a b. (Integral a, Num b) => a -> b fromIntegralInt 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!---- <<http://github.com/LeventErkok/hArduino/raw/master/System/Hardware/Arduino/SamplePrograms/Schematics/Distance.png>>distance ::IO()distance :: IO () distance =Bool -> FilePath -> Arduino () -> IO () withArduino Bool FalseFilePath "/dev/cu.usbmodemFD131"forall a b. (a -> b) -> a -> b $doPin -> PinMode -> Arduino () setPinMode Pin sensor PinMode INPUT Pin -> PinMode -> Arduino () setPinMode Pin led PinMode OUTPUT forall {b}. Arduino b update wheresensor :: Pin sensor =Word8 -> Pin digital Word8 2led :: Pin led =Word8 -> Pin digital Word8 13measure :: Arduino () measure =doMaybe Int mbd <-Pin -> Bool -> Int -> Maybe Int -> Arduino (Maybe Int) pulse Pin sensor Bool TrueInt 10forall a. Maybe a NothingcaseMaybe Int mbd ofMaybe Int Nothing->forall (m :: * -> *) a. MonadIO m => IO a -> m a liftIOforall a b. (a -> b) -> a -> b $FilePath -> IO () putStrLnFilePath "Distance: No measurement received."JustInt d ->doletc :: Float c =Int -> Float microSecondsToCentimeters Int d forall (m :: * -> *) a. MonadIO m => IO a -> m a liftIOforall a b. (a -> b) -> a -> b $FilePath -> IO () putStrLnforall a b. (a -> b) -> a -> b $FilePath "Distance: "forall a. [a] -> [a] -> [a] ++forall a. RealFloat a => Maybe Int -> a -> ShowS showGFloat(forall a. a -> Maybe a JustInt 2)Float c FilePath " centimeters."Pin -> Bool -> Arduino () digitalWrite Pin led (Float c forall a. Ord a => a -> a -> Bool <Float 5)update :: Arduino b update =forall (f :: * -> *) a b. Applicative f => f a -> f b foreverforall a b. (a -> b) -> a -> b $doArduino () measure Int -> Arduino () delay Int 1000