I2C Helpers
Drive an I2C bus (native Linux i2c-dev or a CH347 USB bridge) from Lua. Each helper builds a request message and
sends it on the configured I2C connection. All helpers return true once the request is queued, or raise a Lua runtime
error on invalid parameters.
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 bus operations, e.g. issuing a write and
reading the result a few milliseconds later.
Request Functions
i2c_scan(addr_start, addr_end, connection_id, delay_ms) → boolean
Probe the bus for devices in the inclusive [addr_start, addr_end] address range.
addr_start(number, optional) - First 7-bit address to probe (default:0x03)addr_end(number, optional) - Last 7-bit address to probe (default:0x77)connection_id(number, optional) - Target connection (default:0)delay_ms(number, optional) - Delay delivery by this many milliseconds (default:0)
The defaults match the conventional i2cdetect range (skipping reserved low/high addresses).
i2c_read(address, register, length, connection_id, delay_ms) → boolean
Read length bytes from a device, optionally after writing a register/command byte first (the common
write-register-then-read pattern).
address(number) - 7-bit slave address0x00–0x7F(required; 10-bit addressing is not supported)register(number, optional) - Register/command byte written before the read; passnilto read directlylength(number) - Number of bytes to read (required, must be> 0)connection_id(number, optional) - Target connection (default:0)delay_ms(number, optional) - Delay delivery by this many milliseconds (default:0)
i2c_write(address, register, data, connection_id, delay_ms) → boolean
Write bytes to a device, optionally prefixed by a register/command byte. A request must carry a register and/or
payload bytes.
address(number) - 7-bit slave address0x00–0x7F(required)register(number, optional) - Register/command byte written beforedata; passnilto write raw bytesdata(string) - Payload bytes to write (can be empty ifregisteris set)connection_id(number, optional) - Target connection (default:0)delay_ms(number, optional) - Delay delivery by this many milliseconds (default:0)
Handling Responses
Read and scan results arrive as ordinary RX messages in on_receive(). Use message:get_metadata("i2c_op") to
identify the result type. Write confirmations and errors are emitted as engine events, not RX messages.
i2c_op metadata | Message kind | Payload |
|---|---|---|
read_response | RX | The bytes read; i2c_address (and i2c_register, if any) in metadata |
scan_response | RX | A 0x78-byte i2cdetect-style grid: grid[addr] = addr if a device ACKed |
write_response | event | i2c_write event with i2c_address metadata |
error | event | i2c_error event; the error value holds the message |
Example: read a register and parse the response
local SENSOR = 0x48 -- e.g. a temperature sensor
local TEMP_REG = 0x00
function on_timer(now_ms)
-- Write the register pointer, then read 2 bytes back
i2c_read(SENSOR, TEMP_REG, 2, 0)
end
function on_receive()
if message:get_metadata("i2c_op") ~= "read_response" then return false end
-- 12-bit temperature in the top bits of a big-endian 16-bit word
local raw = read_i16_be(message.payload, 1)
local celsius = raw / 256.0
message:add_float_value("temp_c", celsius)
return true
end
Example: scan the bus and log detected addresses
function on_start()
i2c_scan(0x03, 0x77, 0)
end
function on_receive()
if message:get_metadata("i2c_op") ~= "scan_response" then return false end
for addr = 0, #message.payload - 1 do
-- grid[addr] == addr means the device ACKed at that address
if read_u8(message.payload, addr + 1) ~= 0 then
log("info", string.format("I2C device found at 0x%02X", addr))
end
end
return false
end