A simple circuit, an Arduino, and Haskell

I recently had loads of fun attending a Nodebots AU event in Sydney. (Thanks a lot to Damon and Andrew for organising, and NICTA for the venue!) I got to muck around with some simple circuits and drive them with Javascript. Towards the end of the day I was running out of time and creativity to do anything fancy, so I decided to see if I could get one of the circuits working with Haskell.

Nodebot prerequisites

I got a Node ARDX kit at the event, and followed the Nodebots AU setup guide to get all the software bits and pieces.

For Haskelling, I used my existing Haskell installation, then created a new cabal sandbox and installed the hArduino package (v0.9) into it.

A simple circuit

Here’s a simple circuit that includes a potentiometer and a bunch of LEDs. The idea is that as someone turns up the potentiometer, the number of LEDs switched on increases accordingly. (Yes, this may seem somewhat unimpressive, but as a complete newbie who managed to do this without blowing anything up, I’m calling it a win! :))

DISCLAIMER: While I somehow managed to avoid blowing anything up while attempting this, I don’t know what I’m doing and so can’t guarantee that this won’t destroy anything you value. Use at your own risk! :)

So now I’m in my cabal sandbox and it’s time to write some Haskell. Here’s the main outline of the program (with some explanatory comments added).

After the initialisation stuff, the main bit of the program is the run loop, which polls the potentiometer and updates the LEDs whenever the value changes.

The updateLeds and related code looks like this:

The updateLeds function takes the potentiometer value and works out how many LEDs it needs to turn on based on the numLedsOn function. It then loops through each numbered LED and turns it on or off based on whether the ledNum <= maxLedNum we need to switch on.1

numLedsOn doesn’t need to be a separate function like this, but I found it helped to be able to test my arithmetic independently of hardware. :) (We could also get away without specifying any types, but I find doing so makes it easier for me to read.)

Running this… er… ‘masterpiece’

Rather than setup a build, I just ran cabal repl from my sandbox to get a GHCi with the hArduino package accessible, then loaded and ran the code:

ghci> :load lights.hs
ghci> main

Now I could finally fulfill my life-long dream of adjusting LEDs using a twirly dial! Hooray! :)

1. The updateLeds loop is a bit neater in applicative form, but assumes familiarity with the operators: for_ (zip leds [1..]) $digitalWrite <$> fst <*> ((<= maxLedNum) . snd)