Stephen Smith's Blog

Musings on Machine Learning…

Archive for February 2018

Erlang on the Raspberry Pi

leave a comment »

Introduction

Erlang is a rather interesting programming language with a number of rather unique properties. If you are used to procedural languages like C or its many variants, then Erlang will appear very different. Erlang was originally developed by Ericsson to program telephone switches. The name is either based on Ericsson Language or is named after Agner Krarup Erlang depending on who you ask. In Erlang there are no loops, all loops are accomplished via recursion. Similarly once a variable is assigned, it can never be changed (is immutable). A lot of the function execution is controlled via pattern matching. Beyond the basic language the Erlang system is used to create highly available, scalable fault tolerant systems. You can even swap code on the fly without stopping the system. Erlang is still used in many telephony type applications, but it is also used to create highly reliable and scalable web sites. The best known being WhatsApp. Plus Facebook, Yahoo and many others have services implemented in Erlang serving massive numbers of users.

In this article we’ll begin to look at the basic language and consider an implementation of our flashing LED program for the Raspberry Pi implemented in pure Erlang. ERLang runs on most operating systems and is open source now. It is easy to add to the Raspberry Pi and is a very good system if you want to make use of a cluster of Raspberry Pis.

How to Run the Program

Erlang doesn’t come pre-installed with Raspbian, but it’s easy to add with the command:

sudo apt-get install erlang

After this completes you are good to go.

Erlang includes a terminal based command system where you can compile modules and call functions. To run the programs included here, you need to save the first file as lights.erl and the second as gpio.erl. Then you can compile and execute the program as indicated in the screenshot of my terminal window below:

Some things to note:

  1. Erlang is case sensitive and case has meaning. For instance variables start with a capital letter and functions with a lowercase letter.
  2. Punctuation is very important. The periods end a statement and in the erl shell will cause it to execute. If you miss the period, nothing will happen until you enter one (it assumes you have more text to enter). Similarly inside functions , and ; have a specific meaning that affects how things run.
  3. You do everything by calling functions both in the shell and in the Erlang language. So the c() function compiles a module (produces a .beam file). The q() function exits the shell after terminating all programs. lights:flashinglights() is our exported entry point function to run the program with. You can also call things like ls() to get a directory listing or cd() to change directories or pwd() to find out where you are. Remember to enter any lines with a period to terminate the line.
  4. To access the gpio /sys files, erl must be run from sudo. You could fix the file system permissions, but this seems easy enough.

Flashing LED Program

Below is my main module to flash the lights. Unlike the C or Fortran version of this program, there is no loop, since loops don’t exist in Erlang. Instead it uses recursion to accomplish the same things. (Actually in the Erlang tutorials there are design patterns on how to accomplish while or for loops with recursion). Notice that once a variable is assigned it can never be changed. But you accomplish the same thing with recursion by passing a modified version of the variable into a function. Similarly you can preserve variables using function closures, but I don’t do that here. I included edoc comments which are Erlang version of JavaDoc. Otherwise this is just intended to give a flavour for the language without going into too much detail.

 

%% @author Stephen Smith
%% @copyright 2018 Stephen Smith
%% @version 1.0.0
%% @doc
%% A erlang implementation of my flashing lights program
%% for the Raspberry Pi.
%% @end

-module(lights).
-export([flashlights/0]).
-author('Stephen Smith').

flashlights() ->
    Leds = init(),
    flash(Leds, 10).

init() ->
    L0 = gpio:init(17, out),
    L1 = gpio:init(27, out),
    L2 = gpio:init(22, out),
    {L0, L1, L2}.

flash(Leds, Times) when Times > 0 ->
    gpio:write(element(1, Leds), 1),
    timer:sleep(200),
    gpio:write(element(1, Leds), 0),
    gpio:write(element(2, Leds), 1),
    timer:sleep(200),
    gpio:write(element(2, Leds), 0),
    gpio:write(element(3, Leds), 1),
    timer:sleep(200),
    gpio:write(element(3, Leds), 0),

    flash(Leds, Times-1);

flash(Leds, Times) when Times =< 0 ->
    true.

Erlang GPIO Library

Rather than write the file access library for the GPIO drivers myself, doing a quick Google search revealed several existing ones including this one from Paolo Oliveira.

 

%% @author Paolo Oliveira <paolo@fisica.ufc.br>
%% @copyright 2015-2016 Paolo Oliveira (license MIT)
%% @version 1.0.0
%% @doc
%% A simple, pure erlang implementation of a module for 
%% <b>Raspberry Pi's General Purpose
%% Input/Output</b> (GPIO), using the standard Linux kernel
%% interface for user-space, sysfs,
%% available at <b>/sys/class/gpio/</b>.
%% @end

-module(gpio).
-export([init/1, init/2, handler/2, read/1, write/2, stop/1]).
-author('Paolo Oliveira <paolo@fisica.ufc.br>').

%% API

% @doc: Initialize a Pin as input or output.
init(Pin, Direction) ->
  Ref = configure(Pin, Direction),
  Pid = spawn(?MODULE, handler, [Ref, Pin]),
  Pid.

% @doc: A shortcut to initialize a Pin as output.
init(Pin) ->
  init(Pin, out).

% @doc: Stop using and release the Pin referenced as file descriptor Ref.
stop(Ref) ->
  Ref ! stop,
  ok.

% @doc: Read from an initialized Pin referenced as the file descriptor Ref.
read(Ref) ->
  Ref ! {recv, self()},
  receive
    Msg ->
      Msg
  end.

% @doc: Write value Val to an initialized Pin referenced as the file descriptor Ref.
write(Ref, Val) ->
  Ref ! {send, Val},
  ok.

%% Internals

configure(Pin, Direction) ->
  DirectionFile = "/sys/class/gpio/gpio" ++ integer_to_list(Pin) ++ "/direction",

  % Export the GPIO pin
  {ok, RefExport} = file:open("/sys/class/gpio/export", [write]),
  file:write(RefExport, integer_to_list(Pin)),
  file:close(RefExport),

  % It can take a moment for the GPIO pin file to be created.
  case filelib:is_file(DirectionFile) of
      true -> ok;
      false -> receive after 1000 -> ok end
  end,

  {ok, RefDirection} = file:open(DirectionFile, [write]),
  case Direction of
    in -> file:write(RefDirection, "in");
    out -> file:write(RefDirection, "out")
  end,
  file:close(RefDirection),
  {ok, RefVal} = file:open("/sys/class/gpio/gpio" ++ integer_to_list(Pin) ++ "/value", [read, write]),
  RefVal.

release(Pin) ->
  {ok, RefUnexport} = file:open("/sys/class/gpio/unexport", [write]),
  file:write(RefUnexport, integer_to_list(Pin)),
  file:close(RefUnexport).

% @doc: Message passing interface, should not be used directly, it is present for debugging purpose.
handler(Ref, Pin) ->
  receive
    {send, Val} ->
      file:position(Ref, 0),
      file:write(Ref, integer_to_list(Val)),
      handler(Ref, Pin);
    {recv, From} ->
      file:position(Ref, 0),
      {ok, Data} = file:read(Ref, 1),
      From ! Data,
      handler(Ref, Pin);
    stop ->
      file:close(Ref),
      release(Pin),
      ok
   end.

%% End of Module.

Summary

Erlang is a very interesting language. If you are interested in functional programming or how to create highly scalable reliable web servers, then Erlang is definitely worth checking out. We only looked at a quick introduction to the language, really by example. There are lots of good documentation, tutorials and samples just a Google search away. Perhaps in a future article we’ll look at processes and messages and how to build such a highly scalable server.

 

Advertisements

Written by smist08

February 18, 2018 at 11:59 pm

Posted in raspberry pi

Tagged with , ,

Refurbishing an Old Laptop

with one comment

Introduction

My wife typically used an HP laptop running Windows 10. This laptop is probably about three years old now. Unfortunately she dropped it off the bed onto a cement floor (she claims one of the dogs pushed it off the bed, but I’m suspicious). She actually broke its fall with her foot which is very bruised now, and then it hit the floor after her foot. The laptop then stopped working. She took the laptop to a coffee shop and spilled coffee on it. This didn’t help. She then gave it to me to see if I could get it working. I took it apart to see if it was just a matter of some wires coming loose. Sadly this wasn’t the case. This blog article recounts my attempts to disassemble and repair the laptop, which I successfully accomplished. I’m writing this article on said laptop, while my wife now uses my MacBook Air.

Diagnosing the Problem

On bootup the laptop displayed a text message prompt saying no boot device present. To me this meant that the screen and processor were still working and that the likely problem was the hard drive. After all the harddrive is mechanical with moving parts and likely to be damaged by a shock such as hitting the floor (or a foot). So my first thought was to take it apart and ensure the cables connecting the harddrive were in place.

Opening the Case

It turns out an HP laptop is held together by a lot of screws and many of the screws are hidden behind plastic plugs, the laptop’s feet and various other sneaky bits of plastic. Plus there is a bead of glue around the case that needed to be broken. My first attempt to remove all the screws didn’t allow me inside. Fortunately for doing DIY repairs, there is YouTube. Doing a quick search revealed lots of videos on opening HP laptops and showed a lot of complaining about how HP makes this unnecessarily complex. Anyway watching one of the videos revealed to me where to look for the additional screws (behind some nondescript covers) and allowed me to get the case open.

I removed the hard drive, made sure all the cables were snug and put it back together. And the same result. So I assumed the harddrive was either physically broken or the boot sectors had somehow been erased. So I thought I may as well try installing Ubuntu Linux and repurpose the laptop as a Linux machine. After all running Windows 10, the laptop has been getting slower and slower, so giving up on Windows 10 seemed like a good idea.

Installing Ubuntu Linux

I downloaded an ISO image of Ubuntu Linux for desktop computers. And then installed this onto a USB key to make a bootable USB with Linux. I did this on a really old AMD Windows 7 laptop. Its slow but it’s always been reliable and since I’ve uninstalled nearly everything from it, it works fairly well. Anyway Ubuntu has really good instructions on how to do this at their website. You just download the ISO image and then use the Rufus utility program to copy it to the USB making it bootable.

I then put it in the damaged laptop and booted it up. At this point I could run Ubuntu Linux from the USB or run the Ubuntu installation program. That both of these worked gave me more confidence that the only problem was the laptop’s hard drive. Anyway I went ahead and tried to install Ubuntu Linux, which goes quite a long way before it finally tries to format the hard drive. This failed. So I concluded the harddrive was physically damaged and useless.

Fortunately I have a couple of other laptop hard drives lying around from even older laptops which I could try. The first one I tried didn’t work, so I guess that one is toast as well. But the second one I tried worked. The Ubuntu installation program was able to format the drive and the installation finished successfully. My impression is that installing Linux is now even easier than installing Windows. It didn’t ask too many questions. The screens were simple and easy to understand.

Now I had the laptop restored. Even using the old harddrive, my impression is that the laptop is much faster now running Ubuntu. Of course now I don’t need to run all that Windows stuff that slows computers down so much (like Windows Defender).

Adding Programs

Ubuntu, like Raspbian is based on Debian Linux so anything I’ve blogged about installing things on my Raspberry also works pretty much the same. Plus Ubuntu comes with Firefox, LibreOffice and a number of other useful programs already installed. I was able to quickly add Chrome, Macchanger, Gimp and Tensorflow. For amateur radio there is a program called Chirp that can be used to program most radios. I never got Chirp to talk to my radio from my MacBook due to supposed driver incompatibilities with the USB to serial cable. But when I added Chirp to Ubuntu, it just worked and communicated with my radio no problem, first try.

With my MacBook I use an external drive to hold my photo library since its so large. I use one that is formatted for the MacOS filesystem, so I wasn’t sure it would work connected to Ubuntu, but when I plugged it in, Ubuntu recognized it and automatically mounted it with no problems. I imagine this is since both operating systems are Unix based and their file systems are compatible. I’ve never tried to make this work with Windows, because the instructions are rather daunting and require quite a bit of extra software to be installed.

Summary

The end result of all this is that I have a new refurbished laptop which I’m now using as my regular laptop running Ubuntu Linux. My wife is happily continuing writing her novels on the MacBook Air. And at least for now we don’t need to buy a new laptop. Perhaps we will down the road if we see a really good deal, but it isn’t an emergency. I never feel rushed to buy a new computer since they keep getting better all the time, plus prices are bit high right now because of the run on graphics cards by people doing BitCoin mining. Might be nice to let this run its course first.

 

Written by smist08

February 1, 2018 at 9:48 pm

Posted in Life

Tagged with , , ,