GPIO Helpers
Drive general-purpose I/O pins from Lua. GPIO is served by two transports: the CH347 USB bridge and the unified
Linux Peripherals transport (a /dev/gpiochipN on an embedded board such as a Raspberry Pi). It is driven only from
Lua — there is no message-input form. Each helper builds a request message and sends it on the configured connection. All
helpers return true once the request is queued, or raise a Lua runtime error on invalid parameters.
Pins are addressed by line number. On a CH347 that is the pin index 0–7. On the Linux transport it is the line
offset on the configured gpiochip — on a Raspberry Pi those offsets are the BCM numbers (e.g. 25 for GPIO 25). A
backend with a fixed pin count (the CH347) rejects out-of-range lines.
All helpers accept an optional trailing connection_id (default: 0) selecting the target connection, followed by an
optional delay_ms that schedules the request delay_ms milliseconds in the future instead of sending it immediately
(default: 0 — send now). This is handy for inserting settling time between operations, e.g. driving a pin high, then
reading an input a few milliseconds later.
Request Functions
gpio_write(line, level, connection_id, delay_ms) → boolean
Drive a single line as an output to the given level. This is the convenient single-line form of gpio_set.
line(number) - Line number (required)level(number|boolean) - Output level:0/false= low, non-zero/true= high (required)connection_id(number, optional) - Target connection (default:0)delay_ms(number, optional) - Delay delivery by this many milliseconds (default:0)
gpio_set(ops, connection_id, delay_ms) → boolean
Apply a batch of per-line updates at once. ops is a table (array) of entries, each a table with these fields:
line(number) - Line number (required)output(boolean, optional) -trueconfigures the line as an output (default),falseas an inputlevel(boolean|number, optional) - For an output, the level to drive:true/non-zero = high (defaultfalse/low)
For example, gpio_set({ { line = 24, output = true, level = true }, { line = 25, output = false } }) drives line 24
high and configures line 25 as an input.
gpio_get(lines, connection_id, delay_ms) → boolean
Read the level of one or more lines. lines is either a single line number or a table (array) of line numbers. The
result arrives as an RX message in on_receive() (see below).
lines(number | table) - A line number, or an array of line numbers (required)connection_id(number, optional) - Target connection (default:0)delay_ms(number, optional) - Delay delivery by this many milliseconds (default:0)
Handling Responses
Read results arrive as ordinary RX messages in on_receive(). Use message:get_metadata("gpio_op") to identify the
result type. Set confirmations and errors are emitted as engine events, not RX messages.
gpio_op metadata | Message kind | Payload |
|---|---|---|
get_response | RX | count, then line:u32, value:u8 per line; each level also in gpio_line_<n> |
set_response | event | gpio_set event; the applied batch is echoed in the payload |
error | event | gpio_error event; the error value holds the message |
In a get_response, the simplest way to read a line's level is the per-line metadata gpio_line_<n> — e.g. the level of
line 25 is message:get_metadata("gpio_line_25"), which returns the integer 0 or 1.
Example: blink an LED on line 25
local LED = 25 -- gpiochip line offset (BCM 25 on a Raspberry Pi)
local on = false
function on_timer(now_ms)
on = not on
gpio_write(LED, on)
end
Example: read a button on line 24
local BTN = 24 -- wired as an input
function on_start()
gpio_set({ { line = BTN, output = false } }) -- configure as input
end
function on_timer(now_ms)
gpio_get(BTN) -- poll the line
end
function on_receive()
if message:get_metadata("gpio_op") ~= "get_response" then return false end
local pressed = message:get_metadata("gpio_line_" .. BTN) == 1
message:add_int_value("button", pressed and 1 or 0)
return true
end