In a couple previous blogs I looked at using Lua to read/write with Raspberry GPIO pin, and creating simple text based (ncurses) Lua interfaces.
The Lua LÖVE Graphic engine is very popular for 2D gaming.
In this blog I wanted to document how I used Lua LÖVE Graphics with Raspberry Pi data, specifically I’ll look at:
- Writing Text with different colours and Font sizes
- Use a timer to periodically update the screen with Raspberry Pi temperatures
- User keys to toggle Pi GPIO
- Use button images to toggle logic
Getting Started with LÖVE Graphics
Rather than LÖVE being a graphic library it’s a replacement Lua interpreter, so you run your code directly through LÖVE. To install LÖVE:
sudo apt-get update
sudo apt-get install love
You can check that love is running by:
pi@raspberrypi:~/ $ love --version LOVE 11.1 (Mysterious Mysteries)
There are a number of IDE’s that are available, however any text editor will work. I used leafpad on the Pi.
First Example with Text and Keypresses
The LÖVE expects a project to be in it’s own directory with a main.lua file.
My first example was to launch a window with some text and then catch keystrokes. A “q” key will exit the program.
-- My First App -- platform = {} love.window.setTitle("Raspberry Pi Data") function love.draw() -- draw some text and a rectangle -- love.graphics.setColor(1,0,0) -- rgb, use red love.graphics.setFont(love.graphics.newFont(72)) love.graphics.print("Hit q to exit", 200, 200) end function love.keypressed( key ) print(key) if key == "q" then print( "Quiting Now") love.event.quit() end end
This program is call main.lua . An example of this program running with output:
pi@raspberrypi:~/lua1 $ love ./ a b q Quiting Now
Add a Timer Loop
There are a number of timer loop options. I found that some of these options however would take a lot of background CPU resources. One solution that worked well for me was to add a cron function from : https://github.com/kikito/cron.lua
I downloaded this code (cron.lua) and put it into my working project directory.
For this example I wanted to show the Raspberry Pi’s GPU temperatures. For the GPU temperature, a Pi command line utility exists:
pi@raspberrypi:~ $ /opt/vc/bin/vcgencmd measure_temp temp=44.0'C
This code example includes:
- A reference to a cron file, and a timer variable is setup with a getGPU function
- a shell to the command line : /opt/vc/bin/vcgencmd measure_temp , and then the output was read into a variable (GPU).
- the love.draw function is refreshed with the love.update function.
-- Dynamically show the GPU temperature platform = {} love.window.setTitle("Raspberry Pi Data") local cron = require 'cron' -- this file is in the working dir local msg = 0 local timer = cron.every(5, function() msg = getGPU() end) function getGPU() -- read the command line output f = assert (io.popen ("/opt/vc/bin/vcgencmd measure_temp")) for line in f:lines() do GPU = line print(line) end return GPU end function love.update(dt) timer:update(dt) end function love.draw() love.graphics.setColor(0,1,0) love.graphics.setFont(love.graphics.newFont(72)) love.graphics.print(msg, 200, 200) love.graphics.setColor(0,0,1) love.graphics.setFont(love.graphics.newFont(24)) love.graphics.print("Hit q to quit", 10, 10) end function love.keypressed( key ) print(key) if key == "q" then print( "Q - quit has been pressed!") love.event.quit() end end
The output will look something like:
After I got the basic timer function working my next step will be to look at creating dynamic bars for Pi Sensors.
GPIO Reads and Writes
There are couple of choices for doing Lua connections to GPIO pins.
The lua-periphery library works well but it required sudo rights. For a command line program this isn’t a problem but by default the Raspberry Pi will not allow X-windows to run under super-user. A way to run X-Windows with sudo is:
sudo XAUTHORITY=$HOME/.Xauthority love /mypath_dir
Perhaps a simpler approach is to run the gpio command line program (this is pre-install on the PI’s). Below is some code that uses keystrokes to toggle a GPIO pin.
-- Toggle GPIO pins with keystrokes function love.draw() love.graphics.setColor(0,0,1) love.graphics.setFont(love.graphics.newFont(24)) love.graphics.print("Keys: 0 = off, 1 = on, q to quit", 10, 10) love.graphics.setColor(0,1,0) love.graphics.setFont(love.graphics.newFont(72)) f = assert (io.popen ("gpio read 7")) for line in f:lines() do pin7 = line print(line) end love.graphics.print("Pin 7 : " .. pin7, 200, 200) end function love.keypressed( key ) print(key) if key == "0" then os.execute("gpio write 7 0") end if key == "1" then os.execute("gpio write 7 1") end if key == "q" then print( "Q - quit has been pressed!") love.event.quit() end end
The output will be:
Buttons Toggles
Button images can be defined in the load function, then in the draw function they can be drawn based on some logic. Below is a example with two buttons (red/green), the mousepressed function will catch mouse clicks on the x-y sizing of the image. Then some logic was added to toggle between the two red/green buttons and text feedback.
-- Love 2 Button Example -- platform = {} love.window.setTitle("Raspberry Pi Data") local buttoncolor = "red" function love.load() red = love.graphics.newImage("red.png") green = love.graphics.newImage("greenbutton.jpeg") end function love.update(dt) end function love.draw() love.graphics.setBackgroundColor( 1,1, 1) buttonx = 10 buttony = 10 if buttoncolor == "red" then love.graphics.draw(red,buttonx,buttony) r = 1 g = 0 else love.graphics.draw(green,buttonx,buttony) r = 0 g = 1 end love.graphics.setFont(love.graphics.newFont(48)) love.graphics.setColor(0,0,0) love.graphics.print("Click button\n 'q' to quit", 350, 20) love.graphics.setColor(r,g,0) love.graphics.print("Button State: " .. buttoncolor, 10, 350) love.graphics.setColor(1,1,1) end function love.mousepressed(mx, my, button) if button == 1 and mx >= buttonx and mx < buttonx + red:getWidth() and my >= buttony and my < buttony + red:getHeight() then if buttoncolor == "red" then buttoncolor = "green" else buttoncolor = "red" end end end function love.keypressed( key ) print(key) if key == "q" then print( "q - quit has been pressed!") love.event.quit() end end
The button image and the “Button State” text will toggle each time the button is clicked.
Final Comments
I found that I was able to do all the things that I needed for my Raspberry Pi project, however I struggled with the documentation and examples.
For me this was a chance to learn Love, but I would pick Python over Lua/Love for Raspberry Pi projects. I found that Python with Tkinter was considerably faster with a lot more examples.