packages feed

hArduino 0.7 → 0.8

raw patch · 8 files changed

+164/−5 lines, 8 files

Files

CHANGES.md view
@@ -1,7 +1,13 @@ * Hackage: (http://hackage.haskell.org/package/hArduino) * GitHub:  (http://leventerkok.github.com/hArduino) -* Latest Hackage released version: 0.7+* Latest Hackage released version: 0.8++### Version 0.8, 2013-12-15+ * Add support for Piezo speakers+ * Add simple musical note playing support, and a+   jingle-bells playing example. (Not a great+   rendering, but still recognizable!)  ### Version 0.7, 2013-11-09  * Export LCD type, for ease of programming
System/Hardware/Arduino.hs view
@@ -17,8 +17,8 @@   -- * Programming the Arduino   -- ** Pins   , analog, digital, pin, Pin, PinMode(..), setPinMode-  -- ** Analog input-  , analogRead+  -- ** Analog input/output (PWM)+  , analogRead, analogWrite   -- ** Digital I/O   , digitalWrite, digitalRead   -- ** Programming with triggers
System/Hardware/Arduino/Data.hs view
@@ -9,7 +9,6 @@ -- Underlying data structures ------------------------------------------------------------------------------- -{-# LANGUAGE DeriveFunctor               #-} {-# LANGUAGE GeneralizedNewtypeDeriving  #-} {-# LANGUAGE NamedFieldPuns              #-} {-# LANGUAGE RankNTypes                  #-}@@ -458,6 +457,7 @@                                    , digitalReportingPins = dPins                                    }                     return (bst', acts1 ++ acts2)+getModeActions _ PWM    = return [] getModeActions _ OUTPUT = return [] getModeActions _ SERVO  = return [] getModeActions p m      = die ("hArduino: getModeActions: TBD: Unsupported mode: " ++ show m) ["On pin " ++ show p]
System/Hardware/Arduino/Firmata.hs view
@@ -264,6 +264,20 @@               Just (Right v) -> v               _              -> 0 -- no (correctly-typed) value reported yet, default to 0 +-- | Write a PWM analog value to a pin. The argument is an 'Int', indicating the duty cycle.+-- @0@ means off; @255@ means always on. Intermediate values will create a square wave+-- on that pin with the given duty-cycle+analogWrite :: Pin -> Int -> Arduino ()+analogWrite p' dc = do+   (p, _) <- convertAndCheckPin "analogWrite" p' PWM+   when (dc < 0 || dc > 255) $ die ("Invalid duty-cycle value for PWM write on pin " ++ show p)+                                   [ "Values should be between 0 and 255"+                                   , "Received: " ++ show dc+                                   ]+   send $ AnalogPinWrite p (fromIntegral lsb) (fromIntegral msb)+  where lsb = dc .&. 0x7f+        msb = (dc `shiftR` 7) .&. 0x7f+ -- | Set the analog sampling interval, in milliseconds. Arduino uses a default of 19ms to sample analog and I2C -- signals, which is fine for many applications, but can be modified if needed. The argument -- should be a number between @10@ and @16384@; @10@ being the minumum sampling interval supported by Arduino
System/Hardware/Arduino/Parts.hs view
@@ -17,11 +17,14 @@    ,  module System.Hardware.Arduino.Parts.ShiftRegisters       -- * Servo-motors    ,  module System.Hardware.Arduino.Parts.Servo+      -- * Piezo-speakers+   ,  module System.Hardware.Arduino.Parts.Piezo    ) where  import System.Hardware.Arduino.Parts.LCD import System.Hardware.Arduino.Parts.SevenSegmentCodes import System.Hardware.Arduino.Parts.ShiftRegisters import System.Hardware.Arduino.Parts.Servo+import System.Hardware.Arduino.Parts.Piezo  {-# ANN module "HLint: ignore Use import/export shortcut" #-}
+ System/Hardware/Arduino/Parts/Piezo.hs view
@@ -0,0 +1,91 @@+-------------------------------------------------------------------------------------------------+-- |+-- Module      :  System.Hardware.Arduino.Parts.Piezo+-- Copyright   :  (c) Levent Erkok+-- License     :  BSD3+-- Maintainer  :  erkokl@gmail.com+-- Stability   :  experimental+--+-- Abstractions for piezo speakers. +-------------------------------------------------------------------------------------------------++{-# LANGUAGE NamedFieldPuns #-}+module System.Hardware.Arduino.Parts.Piezo(+   -- * Declaring a piezo speaker+     Piezo, speaker+   -- * Notes you can play, and durations+   , Note(..), Duration(..)+   -- * Playing a note, rest, or silencing+   , playNote, rest, silence+   -- * Play a sequence of notes:+   , playNotes+   ) where++import Data.Bits  (shiftR, (.&.))+import Data.Maybe (fromMaybe)++import System.Hardware.Arduino+import System.Hardware.Arduino.Comm+import System.Hardware.Arduino.Data++-- | A piezo speaker. Note that this type is abstract, use 'speaker' to+-- create an instance.+data Piezo = Piezo { piezoPin :: IPin  -- ^ The internal-pin that controls the speaker+                   , tempo    :: Int   -- ^ Tempo for the melody+                   }++-- | Create a piezo speaker instance.+speaker :: Int            -- ^ Tempo. Higher numbers mean faster melodies; in general.+        -> Pin            -- ^ Pin controlling the piezo. Should be a pin that supports PWM mode.+        -> Arduino Piezo+speaker t p = do debug $ "Attaching speaker on pin: " ++ show p+                 setPinMode p PWM+                 (ip, _) <- convertAndCheckPin "Piezo.speaker" p PWM+                 return Piezo { piezoPin = ip, tempo = t }++-- | Musical notes, notes around middle-C+data Note     = A | B | C | D | E | F | G | R  deriving (Eq, Show)  -- R is for rest++-- | Beat counts+data Duration = Whole | Half | Quarter | Eight deriving (Eq, Show)++-- | Convert a note to its frequency appropriate for Piezo+frequency :: Note -> Int+frequency n = fromMaybe 0 (n `lookup` fs)+ where fs = [(A, 440), (B, 493), (C, 261), (D, 294), (E, 329), (F, 349), (G, 392), (R, 0)]++-- | Convert a duration to a delay amount+interval :: Piezo -> Duration -> Int+interval p Whole   = 8 * interval p Eight+interval p Half    = 4 * interval p Eight+interval p Quarter = 2 * interval p Eight+interval p Eight   = tempo p++-- | Turn the speaker off+silence :: Piezo -> Arduino ()+silence (Piezo p _) = send $ AnalogPinWrite p 0 0++-- | Keep playing a given note on the piezo:+setNote :: Piezo -> Note -> Arduino ()+setNote (Piezo p _) n = send $ AnalogPinWrite p (fromIntegral lsb) (fromIntegral msb)+   where f   = frequency n+         lsb = f .&. 0x7f+         msb = (f `shiftR` 7) .&. 0x7f++-- | Play the given note for the duration+playNote :: Piezo -> (Note, Duration) -> Arduino ()+playNote pz (n, d) = do setNote pz n+                        delay (interval pz d)+                        silence pz++-- | Play a sequence of notes with given durations:+playNotes :: Piezo -> [(Note, Duration)] -> Arduino ()+playNotes pz = go+  where go []            = silence pz+        go (nd@(_, d):r) = do playNote pz nd+                              delay (interval pz d `div` 3) -- heuristically found.. :-)+                              go r++-- | Rest for a given duration:+rest :: Piezo -> Duration -> Arduino ()+rest pz d = delay (interval pz d)
+ System/Hardware/Arduino/SamplePrograms/JingleBells.hs view
@@ -0,0 +1,43 @@+-------------------------------------------------------------------------------+-- |+-- Module      :  System.Hardware.Arduino.SamplePrograms.JingleBells+-- Copyright   :  (c) Levent Erkok+-- License     :  BSD3+-- Maintainer  :  erkokl@gmail.com+-- Stability   :  experimental+--+-- A (pretty bad!) rendering of Jingle Bells on a piezo speaker+-------------------------------------------------------------------------------++module System.Hardware.Arduino.SamplePrograms.JingleBells where++import System.Hardware.Arduino+import System.Hardware.Arduino.Parts.Piezo++-- | Notes for jingle-bells. Expecting a nice rendering from this encoding+-- on a piezo speaker would be naive.. However, it's still recognizable!+jingleBells :: [(Note, Duration)]+jingleBells =  m1 ++ m1 ++ m3 ++ m4 ++ wait ++ m5 ++ m6 ++ m7 ++ m8 ++ wait+            ++ m1 ++ m1 ++ m3 ++ m4 ++ wait ++ m5 ++ m6 ++ m15 ++ m16+  where m1   = [(E, Quarter), (E, Quarter), (E, Half)]+        m3   = [(E, Quarter), (G, Quarter), (C, Quarter), (D, Quarter)]+        m4   = [(E, Whole)]+        m5   = replicate 4 (F, Quarter)+        m6   = (F, Quarter) : replicate 3 (E, Quarter)+        m7   = [(E, Quarter), (D, Quarter), (D, Quarter), (E, Quarter)]+        m8   = [(D, Half), (G, Half)]+        m15  = [(G, Quarter), (G, Quarter), (F, Quarter), (D, Quarter)]+        m16  = [(C, Whole)]+        wait = [(R, Half)]++-- | Play the jingle-bells on a PWM line, attached to pin 3. We use a +-- tempo of @75@; which is fairly fast. For a slower rendring try @150@+-- or higher values.+--+-- The circuit simple has a piezo speaker attached to pin 3.+--+--  <<http://github.com/LeventErkok/hArduino/raw/master/System/Hardware/Arduino/SamplePrograms/Schematics/Piezo.png>>+main :: IO ()+main = withArduino False "/dev/cu.usbmodemfd131" $ do+                pz <- speaker 75 (pin 3)+                playNotes pz jingleBells
hArduino.cabal view
@@ -1,5 +1,5 @@ Name:          hArduino-Version:       0.7+Version:       0.8 Category:      Hardware Synopsis:      Control your Arduino board from Haskell. Description:   hArduino allows Haskell programs to control Arduino boards (<http://www.arduino.cc>)@@ -32,11 +32,13 @@                     , System.Hardware.Arduino.Parts.ShiftRegisters                     , System.Hardware.Arduino.Parts.SevenSegmentCodes                     , System.Hardware.Arduino.Parts.Servo+                    , System.Hardware.Arduino.Parts.Piezo                     , System.Hardware.Arduino.SamplePrograms.Analog                     , System.Hardware.Arduino.SamplePrograms.Blink                     , System.Hardware.Arduino.SamplePrograms.Button                     , System.Hardware.Arduino.SamplePrograms.Counter                     , System.Hardware.Arduino.SamplePrograms.Distance+                    , System.Hardware.Arduino.SamplePrograms.JingleBells                     , System.Hardware.Arduino.SamplePrograms.LCD                     , System.Hardware.Arduino.SamplePrograms.NumGuess                     , System.Hardware.Arduino.SamplePrograms.Pulse