When I last visited this subject I was on: Step 4. Link a GPIO control library to Erang. To recap, I thought I would need to wrap a C or C++ Raspberry Pi GPIO control library in an Erlang Port or NIF. (Google/Bing that if you want, I’m tired of inserting links everywhere.) Which meant that it was time to buckle down and learn me some Erlang. So I fired up the Kindle app on the Android tablet, and started reading Learn You Some Erlang for Great Good! I think this is great book, but I don’t have anything to compare it to. There may be better books out there for learning Erlang, I just don’t know.
In the spirit of keeping it real, I worked through the examples in the book, using the Erlang shell, running on my RBP. So I got the point of creating Erlang modules, compiling them in the shell, and then invoking the functions contained in the modules. Cool! (Just to be clear, I am nowhere near the end of this book yet) And then it hit me. Before I twist my brain into knots trying to get Erlang to interface with a foreign language library, let’s stop and think for a minute.
As I already knew, the most common way to manipulate the GPIO pins on the RBP, is by reading and writing strings to a predefined set of files. In other words, reading and writing the state of the GPIO pins, is abstracted as file reads and writes. For example:
- Writing: “17” to the file: “/sys/class/gpio/export”
reserves pin 17 of the GPIO, for the process that executed the file write action.
- Writing: “out” to the file: “/sys/class/gpio/ gpio17/direction”
sets pin 17 to be an output pin.
- Writing: “1” to the file: “/sys/class/gpio/ gpio17/value”
sets pin 17 output to a high state or “on”
- Writing: “17” to the file: “/sys/class/gpio/unexport”
releases pin 17 for use by other processes. And so on…
So I was drawn to existing C and C++ code libraries that were already doing that. Well then I thought, Erlang has to be able to read and write files too, so why should I bother trying to create some kind of interface? Just have Erlang do the file reads and writes. Will that work? Of course it will. It has to. I looked up the Erlang syntax for file I/O and soon I was happily turning my LED on and off via Erlang. So here is the first iteration of my pi_gpio.erl module. This is just a shadow, of a real Erlang GPIO library. There is a lot of missing functionality, (Please do not use it in your Mars Rover/Particle Beam Accelerator/Death Ray project.) but it is enough to turn a pin on and off.
ExportFile = string:concat(?GPIO_PATH, "export"),
file:write_file(ExportFile, Pin, [append]).
UnexportFile = string:concat(?GPIO_PATH, "unexport"),
file:write_file(UnexportFile, Pin, [append]).
set_pin_direction(Pin, Direction) ->
file:write_file(direction_file(Pin), Direction, [append]).
set_pin_value(Pin, Value) ->
file:write_file(value_file(Pin), Value, [append]).
PinFolder = string:concat(string:concat(?GPIO, Pin), "/"),
Below is an example of using the pi_gpio module in the Erlang shell, with a comment of what each line does below that.
- Compile the pi_gpio module
- Reserve pin 17 for use by this process
- Set pin 17 to be an output pin
- Turn pin 17 ON
- Turn pin 17 OFF
- Release pin 17 for use by other processes
Step 4. Completed. Just not in the way I expected. Subsequent searches of Github, reveal plenty of other Erlang RBP GPIO libraries, but it was still fun discovering it for myself, and how else am I going to learn?
I think the next step will be creating a continuously running Erlang process that reads the state of an input pin, and flashes the LED in some kind of pattern. I know, flip a switch, turn on an LED. It’s been done millions of times already, on the RBP, but it’s new to me.