lua-periphery is a library for GPIO, LED, PWM, SPI, I2C, MMIO, and Serial peripheral I/O interface access in userspace Linux. It is useful in embedded Linux environments (including Raspberry Pi, BeagleBone, etc. platforms) for interfacing with external peripherals. lua-periphery is compatible with Lua 5.1 (including LuaJIT), Lua 5.2, Lua 5.3, and Lua 5.4, has no dependencies outside the standard C library and Linux, is portable across architectures, and is MIT licensed.
Using Python or C? Check out the python-periphery and c-periphery projects.
Contributed libraries: java-periphery, dart_periphery
localGPIO=require('periphery').GPIO-- Open GPIO /dev/gpiochip0 line 10 with input directionlocalgpio_in=GPIO("/dev/gpiochip0", 10, "in")
-- Open GPIO /dev/gpiochip0 line 12 with output directionlocalgpio_out=GPIO("/dev/gpiochip0", 12, "out")
localvalue=gpio_in:read()
gpio_out:write(notvalue)
gpio_in:close()
gpio_out:close()localLED=require('periphery').LED-- Open LED led0localled=LED("led0")
-- Turn on LED (set max brightness)led:write(true)
-- Set half brightnessled:write(math.floor(led.max_brightness/2))
-- Turn off LED (set zero brightness)led:write(false)
led:close()localPWM=require('periphery').PWM-- Open PWM chip 0, channel 10localpwm=PWM(0, 10)
-- Set frequency to 1 kHzpwm.frequency=1e3-- Set duty cycle to 75%pwm.duty_cycle=0.75-- Enable PWM outputpwm:enable()
pwm:close()localSPI=require('periphery').SPI-- Open spidev1.0 with mode 0 and max speed 1MHzlocalspi=SPI("/dev/spidev1.0", 0, 1e6)
localdata_out= {0xaa, 0xbb, 0xcc, 0xdd}
localdata_in=spi:transfer(data_out)
print(string.format("shifted out {0x%02x, 0x%02x, 0x%02x, 0x%02x}", unpack(data_out)))
print(string.format("shifted in {0x%02x, 0x%02x, 0x%02x, 0x%02x}", unpack(data_in)))
spi:close()localI2C=require('periphery').I2C-- Open i2c-0 controllerlocali2c=I2C("/dev/i2c-0")
-- Read byte at address 0x100 of EEPROM at 0x50localmsgs= { {0x01, 0x00}, {0x00, flags=I2C.I2C_M_RD} }
i2c:transfer(0x50, msgs)
print(string.format("0x100: 0x%02x", msgs[2][1]))
i2c:close()localMMIO=require('periphery').MMIO-- Open am335x real-time clock subsystem pagelocalrtc_mmio=MMIO(0x44E3E000, 0x1000)
-- Read current timelocalrtc_secs=rtc_mmio:read32(0x00)
localrtc_mins=rtc_mmio:read32(0x04)
localrtc_hrs=rtc_mmio:read32(0x08)
print(string.format("hours: %02x minutes: %02x seconds: %02x", rtc_hrs, rtc_mins, rtc_secs))
rtc_mmio:close()
-- Open am335x control module pagelocalctrl_mmio=MMIO(0x44E10000, 0x1000)
-- Read MAC addresslocalmac_id0_lo=ctrl_mmio:read32(0x630)
localmac_id0_hi=ctrl_mmio:read32(0x634)
print(string.format("MAC address: %04x%08x", mac_id0_lo, mac_id0_hi))
ctrl_mmio:close()localSerial=require('periphery').Serial-- Open /dev/ttyUSB0 with baudrate 115200, and defaults of 8N1, no flow controllocalserial=Serial("/dev/ttyUSB0", 115200)
serial:write("Hello World!")
-- Read up to 128 bytes with 500ms timeoutlocalbuf=serial:read(128, 500)
print(string.format("read %d bytes: _%s_", #buf, buf))
serial:close()lua-periphery errors are descriptive table objects with an error code string, C errno, and a user message.
-- Example of error caught with pcall()>status, err=pcall(function () spi=periphery.SPI("/dev/spidev1.0", 0, 1e6) end)
>=statusfalse>dump(err)
{
message="Opening SPI device \"/dev/spidev1.0\": Permission denied [errno 13]",
c_errno=13,
code="SPI_ERROR_OPEN"
}
>-- Example of error propagated to user>periphery=require('periphery')
>spi=periphery.SPI('/dev/spidev1.0', 0, 1e6)
OpeningSPIdevice"/dev/spidev1.0": Permissiondenied [errno13]
>Lua 5.1 does not automatically render the string representation of error objects that are reported to the console, and instead shows the following error message:
>periphery=require('periphery')
>gpio=periphery.GPIO(14, 'in')
(errorobjectisnotastring)
>These errors can be caught with pcall() and rendered in their string
representation with tostring(), print(), or by evaluation in the
interactive console:
>periphery=require('periphery')
>gpio, err=pcall(periphery.GPIO, 14, 'in')
>=tostring(err)
OpeningGPIO: opening'export': Permissiondenied [errno13]
>print(err)
OpeningGPIO: opening'export': Permissiondenied [errno13]
>=errOpeningGPIO: opening'export': Permissiondenied [errno13]
>This only applies to Lua 5.1. LuaJIT and Lua 5.2 onwards automatically render the string representation of error objects that are reported to the console.
man page style documentation for each interface is available in docs folder.
$ sudo luarocks install lua-peripheryClone lua-periphery recursively to also fetch c-periphery, which lua-periphery is built on.
$ git clone --recursive https://github.com/vsergeev/lua-periphery.git
$ cd lua-periphery
$ make clean all
$ sudo make installlua-periphery can then be loaded in lua with periphery = require('periphery').
Set the CROSS_COMPILE environment variable with the cross-compiler prefix when calling make. Your target's sysroot must provide the Lua includes.
$ CROSS=arm-linux- make clean allcd c-periphery && make cleanmake[1]: Entering directory '/home/anteater/projects/software/lua-periphery/c-periphery'rm -rf periphery.a obj tests/test_serial tests/test_i2c tests/test_gpio_sysfs tests/test_mmio tests/test_spi tests/test_gpiomake[1]: Leaving directory '/home/anteater/projects/software/lua-periphery/c-periphery'rm -rf periphery.socd c-periphery; makemake[1]: Entering directory '/home/anteater/projects/software/lua-periphery/c-periphery'mkdir objarm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\" -c src/gpio.c -o obj/gpio.oarm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\" -c src/spi.c -o obj/spi.oarm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\" -c src/i2c.c -o obj/i2c.oarm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\" -c src/mmio.c -o obj/mmio.oarm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\" -c src/serial.c -o obj/serial.oarm-linux-gcc -std=gnu99 -pedantic -Wall -Wextra -Wno-unused-parameter -fPIC -DPERIPHERY_VERSION_COMMIT=\"v2.0.1\" -c src/version.c -o obj/version.oarm-linux-ar rcs periphery.a obj/gpio.o obj/spi.o obj/i2c.o obj/mmio.o obj/serial.o obj/version.omake[1]: Leaving directory '/home/anteater/projects/software/lua-periphery/c-periphery'arm-linux-gcc -std=c99 -pedantic -D_XOPEN_SOURCE=700 -Wall -Wextra -Wno-unused-parameter -fPIC -I. -Iinc -shared src/lua_periphery.c src/lua_mmio.c src/lua_gpio.c src/lua_spi.c src/lua_i2c.c src/lua_serial.c c-periphery/periphery.a -o periphery.so
$ file periphery.soperiphery.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, not stripped
$The tests located in the tests folder may be run under Lua to test the correctness and functionality of lua-periphery. Some tests require interactive probing (e.g. with an oscilloscope), the installation of a physical loopback, or the existence of a particular device on a bus. See the usage of each test for more details on the required setup.
lua-periphery is MIT licensed. See the included LICENSE file.