Julia programming on a Raspberry Pi

Julia is a free and open-source general purpose programming language with an emphasis on scientific computing. Like Python and R, Julia can be used in Jupyter notebooks.

Julia was released in 2012 and compared to the popularity of other programming languages Julia ranks fairly low #24 , (behind Lua and ahead of Perl). Julia appears to be gaining popularity with an 87% increase last year in user downloads.

Some of the reasons that I wanted to look at Julia:

  • Julia scripts can be compiled or run from command line
  • Statistical and plotting libraries are built into Julia
  • Code from : Python, Matlab, Lua can be used directly in Julia
  • Libraries from Java, C, Python
  • Python code can be embedded in Julia script

In this blog I wanted to document my Julia testing on a Raspberry Pi.

Some key take-aways:

  • Integration with Python is awesome. I was able to use Rasp Pi LED’s without any issues.
  • Julia has some nice plotting options
  • Julia is very very slow the first time a new library is loaded from the command line.

Getting Started

Julia is supported on Windows, MacOS and Linux. See the download documentation for your specific system at : https://julialang.org/downloads/. To install Julia on a Raspberry Pi enter:

sudo apt install julia

To check your install, you can run Julia at the command line:

pi@raspberrypi:~ $ julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.5.3
 _/ |\__'_|_|_|\__'_|  |  Raspbian ⛬  julia/1.5.3+dfsg-3+rpi1
|__/                   |

julia> 

Julia packages can be installed at the command line by:

$ julia --eval "using Pkg; Pkg.add('some_package')"

Or within Julia by:

julia> using Pkg
julia> Pkg.add("some_package")

For my setup I used a Pi 4 with a proto shield top and I wired in an LED, a 4 digital tm1637 module and a 2 line I2C LED screen.

Julia with Raspberry Pi GPIO

A Raspberry Pi package “PiGPIO” is installed by:

julia> using Pkg
julia> Pkg.add("PiGPIO")

Once the package is installed a daemon ( pigpiod) is created that the Julia script connects to. The pigpiod daemon is started by:

sudo pigpiod

Below is some code to write to and read from a Pi GPIO pin:

julia> using PiGPIO
julia> ledpin = 17;
julia> p = Pi();
julia> set_mode(p,ledpin, PiGPIO.OUTPUT);
julia> PiGPIO.write(p, ledpin, PiGPIO.HIGH);
julia> PiGPIO.read(p, ledpin)
1

Note: adding a semi-colon at the end of a line will suppress debug information.

GUI’s with Gtk

Like most programming languages Julia has a number of GUI options. For my testing I used the Gtk library which feels quite familiar to the Python Tkinter GUI library.

To install Gtk in Julia:

julia> using Pkg
julia> Pkg.add("Gtk")

Below is a Julia script to create a 2 button window that will turn on/off a GPIO pin:

# 
# Gtk_17.jl - Use a Gtk GUI to toggle a PI GPIO LED
#
using Gtk;
using PiGPIO;

# Setup GPIO 
p=Pi();
led_pin = 17;
set_mode(p, led_pin, PiGPIO.OUTPUT) 

# Init GUI objects
win     = GtkWindow("Toggle a Pi LED", 300, 300);
g       = GtkGrid();

# Text label
label   = GtkLabel(string("Pin : $led_pin"));
# Buttons
btn_on  = GtkButton("ON");
btn_off  = GtkButton("OFF");

# Put GUI widgets into a grid
g[1:2,1] = label;   # Cartesian coordinates, g[x,y]
g[1,2] = btn_on;
g[2,2] = btn_off;

# Show the GUI Window
push!(win, g);
showall(win);

# Callbacks
function turn_on(w1)
	PiGPIO.write(p, led_pin, PiGPIO.HIGH)
	println("ON button pressed")
end
signal_connect(turn_on, btn_on, "clicked")

function turn_off(w2)
	PiGPIO.write(p, led_pin, PiGPIO.LOW)
	println("OFF button pressed")
end
signal_connect(turn_off, btn_off, "clicked")

# Close cleanly
signal_connect(win, :destroy) do widget
    Gtk.gtk_quit()
end
Gtk.gtk_main()

Running a Julia Script

To run the Julia script with some debug and compiler options minimized:

julia -O0 –compile=min –startup=no Gtk_17.jl

Julia Web Server

There are a few web server options. I found that the Genie web frame work was easy to get up and running with minimal code and reading.

Below is an example to call a static web page with a form to turn a GPIO pin on/off:

#
# web2.jl - Julia Web Page with routes to turn on/off a Pi GPIO pin
#
using Genie
using Sockets # to get IP address
using PiGPIO;

# Setup GPIO 
p=Pi();
led_pin = 17;
set_mode(p, led_pin, PiGPIO.OUTPUT) 

# get the Rasp Pi IP address
myip = string(getipaddr() )

println("Loading Genie...")

# get the HTML document
s = open("webjulia.html") 
html_file = read(s, String)

route("/") do
  return html_file
  println("Connected")
end

route("/ON?") do
  PiGPIO.write(p, led_pin, PiGPIO.HIGH)
  return html_file
  println("ON Selected")
end

route("/OFF?") do
  PiGPIO.write(p, led_pin, PiGPIO.LOW)
  return html_file
  println("OFF Selected")
end

# Start the web app on port 8001
up( 8001, myip, async = false)

The HTML page is:

<html>
<head>
<title>Julie GPIO Test Page</title>
</head>
<body>
  <h1>Toggle PI LED</h1>
  <form>
    <button type="submit" formaction="/ON">ON</button>
    <button type="submit" formaction="/OFF">OFF</button>
  </form>
</body>
</html>

To start the Julia script enter:

julia -O0 --compile=min --startup=no web2.jl

Julia calling Python

I thought that it was pretty amazing that script languages like Lua, Matlab, R and Python could be integrated directly into a Julia script.

To enable this functionality the first step is to install the required library. For example to add the Python interface from the command line:

$  julia --eval "using Pkg; Pkg.add('PyCall')"

The PyCall library allows for Python libraries to be used in Julia or Python code can be run directly. An example to run Python code directly to write text to a 2 line I2C LED screen:

julia> using PyCall

julia> py"""
       # Use Python to write text to a 2 line LCD screen
       from rpi_lcd import LCD
       lcd = LCD()
       lcd.text('Hello World!', 1)
       lcd.text('Raspberry Pi', 2)
       """
julia> # Now back into Julia

To do the same functionality using a Python library in Julia:

using PyCall
rpi_lcd = pyimport("rpi_lcd")
lcd = rpi_lcd.LCD()
lcd.text("Hello from Julia", 1)
lcd.text("Raspberry Pi!", 2)

Functions can be created in Python and then called in Julia. An example to call a Python Tkinter window:

using PyCall

py"""

import tkinter as tk

def show_win():
	window = tk.Tk()
	tk.Label(text="Python TK Window from Julia").pack()
	window.mainloop()
"""
py"show_win"()

Plotting

Julia has some good plotting libraries and examples, but they are slow to come up the first time.

I did a dynamic example that plots the Pi’s CPU temperature every 1/4 second.

This example shows a couple of different Julia syntax items:

  • the pipeline command is used for calling Bash command with pipes
  • backtick notation (`) is used for command strings (eg. `echo hello`)
  • append to an array with push!
  • remove the first item in an array with popfirst!
#
# plot_temp.jl - create a dynamic plot of CPU temperature
#
using Plots
println("Show Pi CPU temperature on a plot...")
cputemp = Vector{Float64}()

gr(); # use the GR backend for plotting
display(plot(cputemp))

println("Cycle every 1/4 seconds and add a new temp to the plot...") 
for i = 1:200
   # get the Pi GPU temperature
   t = read(pipeline(`vcgencmd measure_temp`,`awk '{ print substr($1,6,4) }'`), String)
   push!(cputemp, parse(Float64,t) )
   # Limit the array to 10 values
   if length(cputemp) > 50
     popfirst!(cputemp)
   end
   #println(cputemp)   
   display(plot(cputemp, title = "Raspberry Pi CPU Temperature", label = "Deg C"));
   sleep(0.25)
end

As mentioned earlier loading the Plots package the first time is quite slow, if you are working in the Julia command mode you can cut and paste code in without calling “using Plots” multiple times. I found that this greatly improved my testing time. To call a script into the Julia command mode:

julia> include("my_script.jl")

Final Comments

As a Python user l found using Julia PyCall to be great way to re-use existing code.

There are some great features in Julia but until first time call up time is improved it will be frustrating using Julia. I looked at compiling Julia into an executable but unfortunately this isn’t an easy one-step operation.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s