profile picture

Clojure on the BeagleBone part 3 - Blinking an LED with ClojureScript

July 14, 2014 - clojure beaglebone

Intro

The BeagleBone is a 1GHz ARM board with 512Mb of RAM capable of running Linux. The Debian image ships with node.js and a javascript library in BoneScript for interacting with the hardware. Clojurescript provides a compiler for Clojure that targets Javascript, here we will use it to blink an LED on a breadboard using the BeagleBone GPIO.

Hello World with Clojurescript and node.js

First we will ensure that ClojureScript and node.js are setup. Ensure you have followed the instructions in the first part of this series to install Leiningen.

SSH into your BeagleBone and create a file named project.clj with the following contents:

(defproject cljs-nodejs-hello-world "0.0.1"
  :description "Hello World example for clojurescript on node.js"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :plugins [[lein-cljsbuild "1.0.3"]]
  :cljsbuild {
    :builds [{
        :source-paths ["src"]
        :compiler {
          :output-to "lib/hello-world.js"
          :optimizations :simple
          :target :nodejs
          :pretty-print true}}]}
  :dependencies [[org.clojure/clojurescript "0.0-2197"]])

And create a file name src/cljs_helloworld/core.cljs with these contents:

(ns cljs-helloworld.core
  (:require [cljs.nodejs :as nodejs]))

(defn -main [& args]
  (println (apply str (map [\space "world" "hello"] [2 0 1]))))

; Let println work
(nodejs/enable-util-print!)

; Tell node which function to use as main
(set! *main-cli-fn* -main)

Now compile the clojurescript to javascript and run it on your BeagleBone.

$ lein cljsbuild once
$ node lib/hello-world.js

You should see hello world output.

Blinking an LED

This is inspired by an example from the excellent book [Getting Started With BeagleBone][beaglebone-book] by [Matt Richardson][matt-richardson].

schematic

Schematic above was generated using the open source Fritzing.


Note: The GPIO pins can only handle 3.3 volts, so be very careful that you do not accidentally connect a jumper to one of the 5 volt source pins. If you are unsure of what you are doing I would highly recommend reading the system reference manual to make sure you do not damage your board.


Wire up the LED

  1. Using a jumper wire connect Pin 2 on Header P9 (ground) on the BeagleBone to the negative rail on the breadboard.
  2. Place an LED in the breadboard.
  3. Using a jumper wire connect the cathode (shorter) wire of the LED to the negative rail.
  4. Connect one end of a 100 ohm resistor to the anode (longer) wire of the LED.
  5. Using another jumper wire connect the other end of the resistor to Pin 13 on Header P8

Now we are ready to write the code.

ClojureScript code

SSH into your BeagleBone and create a file named project.clj with the following contents:

(defproject cljs-beaglebone-blink-led "0.0.1"
  :description "Hello World example for clojurescript on node.js"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :plugins [[lein-cljsbuild "1.0.3"]]
  :cljsbuild {
    :builds [{
        :source-paths ["src"]
        :compiler {
          :output-to "lib/blink.js"
          :optimizations :simple
          :target :nodejs
          :pretty-print true}}]}
  :dependencies [[org.clojure/clojurescript "0.0-2197"]])

And create a file named src/cljs_blink_led/core.cljs with these contents:

(ns cljs-blink-led.core
  (:require [cljs.nodejs :as nodejs]))

(def bone (nodejs/require "bonescript"))

; Bonescript identifiers related to pins
(def OUTPUT (aget bone "OUTPUT"))
(def HIGH (aget bone "HIGH"))
(def LOW (aget bone "LOW"))


; LEDs
(def led-pin "P8_13")    ; GPIO pin 13 on header P8
(def onboard-led "USR3") ; One of the onboard LEDs

; State of our LEDs
(def led-pin-state (atom LOW))

; Set both pins as an output
(defn setup-pins []
  (.pinMode bone led-pin OUTPUT)
  (.pinMode bone onboard-led OUTPUT))

(defn toggle-digital-pin-state []
  (if (= @led-pin-state HIGH)
    (reset! led-pin-state LOW)
    (reset! led-pin-state HIGH)))


(defn blink-leds []
  (toggle-digital-pin-state)
  (.digitalWrite bone led-pin @led-pin-state)
  (.digitalWrite bone onboard-led @led-pin-state))


(defn -main [& args]
  (setup-pins)
  (js/setInterval blink-leds 1000))

(set! *main-cli-fn* -main)

Now compile the clojurescript to javascript and run it on your BeagleBone.

$ lein cljsbuild once
$ node lib/blink.js

Your LED should now blink on and off every second.