Lua scripting with modules

TILT!Audio features a lua runtime 5.2 to control additional extensions like shakers, LED-lights and also servos.

To make this possible TILT!Audio firmware embeds a lua runtime (lua virtual machine) and loads a “init.lua” script from the sound directory.

The init.lua script already has access to all core lua language features and also the TILT!Audio bindings see lua reference. The binding allows access to the sound engine, communicate via i2c, logging messages and get information about the current installation.

Lua in its language ecosystem also offers modules and package managers that allows installing and managing modules that extend lua features. One of this package managers is luarocks.

Luarocks

Using luarocks as package manager to install a new module together with TILT!Audio is not so straight forward as you can read it on most websites, because the linux running on a TILT!Audio card is tailored down to a minimum to run as efficient as it should to produce sound and nothing else.

What is missing for example is a c compiler that most lua modules require as they come as a combination of lua code and c code.

Also luarocks requires a certain directory structure that is aware of the different lua versions and different places in the system where the lua runtime should look for “modules” (which is *.so and *.lua files).

The TILT!Audio start script does set the required environment variables to let lua runtime find modules, but still not in that way that a module installed by luarocks would expect.

General approach

To make use of luarocks and lua modules we need a second raspberry pi or more precisely a second linux installation on a sd card. Easiest is to use the latest dietpi as this is also the distribution TILT!Audio uses. Other distribution like rasbian or armbian should also work.

For this example I choose a simple module cjson for json decoding and encoding as this module has no further dependencies but still requires native code. You need to use version cjson 2.1.0-1 as the newest is not compatible with lua 5.2 anymore.

Step by Step

  1. install gcc
  2. install lua 5.2 (including dev dependencies)
  3. download latest luarocks tarball
  4. build and configure luarocks
  5. create a private lua module directory /boot/data/lua (same name as it will be in the TA installation)
  6. install a module with luarocks into that directory using –tree option
  7. zip installed modules and copy them over to the TA-installation
  8. adjust LUA_PATH and LUA_CPATH in tiltaudio.sh to match the luarocks config

Alternatively to step 8 you do not change the LUA_PATH and LUA_CPATH in the tiltaudio.sh start script, but instead copy the installed module files into the right directories.

Then copy over the zip file created in line 10 and extracting everything on the TA installation into /boot/data/lua and replace the two export LUA_PATH / LUA_CPATH lines in tiltaudio.sh with the output of the the luarocks path command from line 11 (the line 12 and 13 with the export commands).

After that everything should be ready to use the new cjson module and we can try it out be adding some lua code in the init.lua in /boot/data/sound

Now restart the TILT!Audio service and you should see in the logfile something like this:

As you can see the code gets executed, modules gets loaded and json encode call is executed successfully.

How does luarocks install modules

When you look at the contents of the zip file …

… you see there is a lot of overhead due to luarocks versioned package management and also example code. When you simply want to use the module it comes down to one *.so file and three lua files.

So the alternative instead of copying all that luarocks stuff you could simply only use these five files:

While trying this I discovered a bug in the normal lua path that was set in the start script so far. So also the simple unversioned paths need a minor tweak:

The ?.so and ?.lua at the end was missing, sorry for that, will be fixed in the upcoming versions.

Final note or advice

As you can see with this example “module cjson” (json decoding / encoding) there is already native code involved (the cjson.so file) even though it is a rather simple module.

Native code (also complex lua code) can do all kind of thing like complex computation, consuming a lot of memory, doing high latency network communication so the chance to bring you TILT!Audio down increases the more you do with lua and lua modules. So please keep things as simple and lightweight as possible.

I also cannot provide further programming or debugging support, if you run into problems with lua. Try to get things tested and working outside of the TILT!Audio environment first.

Hope this post helps the more enthusiastic lua programmers in the TILT!Audio world to get something cool to work!