Without filters, no frames are delivered to your script.
Parameters: (variadic, function accepts a variable number of arguments).
Each argument can be either an integer CAN ID or a table (array) of integer CAN IDs. Any number of arguments in any order.
Returns: Nothing.
Lua code:
-- Single ID
can.filter(0x7E0)
-- Multiple IDs
can.filter(0x7E0, 0x7E8)
-- Table of IDs
can.filter({0x100, 0x101, 0x102})
-- Mixed
can.filter(0x123, {0x200, 0x201}, 0x7E0)
Call can.filter() once at the start of your script (before the main loop).
After calling this, no frames will be delivered until new filters are added.
Lua code:
can.clear()
can.count() - Returns the number of CAN frames waiting in this script's receive queue.
Returns: integer - pending frame count.
Lua code:
while can.count() > 0 do
local frame = can.recv()
-- process frame
end
Returns: A CAN frame object, or "nil" if the queue is empty.
The returned frame object has the following fields:
".id" (integer): CAN ID (standard or extended).
".bus" (integer): CAN bus number (1 or 2).
".dlc" (integer): Data length code (0–8).
".data" (data object): Byte array, 0-indexed: data[0] through data[dlc-1].
Lua code:
local frame = can.recv()
if frame then
print(string.format("ID=0x%X bus=%d dlc=%d", frame.id, frame.bus, frame.dlc))
print("Byte 0 = " .. frame.data[0])
end
Data access notes:
"frame.data" is 0-indexed to match CAN byte positions directly.
"#frame.data" returns the DLC (number of bytes).
"tostring(frame)" prints a human-readable representation for debugging.
"tostring(frame.data)" prints the data bytes in hex.
Useful when you want to build a frame incrementally or reuse it.
Parameters:
"id" (integer): CAN ID (0x000 - 0x1FFFFFFF).
"bus" (integer): CAN bus number (1 or 2).
"data_table" (table): (Optional) array of byte values {0x00, ..., 0xFF}.
"dlc" (integer): (Optional) explicit DLC override. Defaults to the length of "data_table", or 0 if no data provided.
Returns: A CAN frame object.
Lua code:
-- Empty 8-byte frame
local tx = can.frame(0x600, 1, {0,0,0,0,0,0,0,0})
-- Modify bytes
tx.data[0] = 0xAB
tx.data[1] = 0xCD
-- Frame with preset data
local status = can.frame(0x321, 1, {0x01, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00})
Legacy form: can.frame(id, bus, dlc) with a plain integer as the third argument creates a zero-filled frame with that DLC.
Accepts either a pre-built frame object or inline arguments. Use a frame object when you need to reuse and modify the same frame across iterations. Use inline arguments for one-off transmissions.
Returns: boolean - true if the frame was queued for transmission, false if the TX buffer is full.
Parameters (style 1 - frame object):
"frame" (CAN frame): A frame previously created by can.frame() or received by can.recv().
Parameters (style 2 - inline):
"id" (integer): CAN ID (0x000 - 0x1FFFFFFF).
"bus" (integer): CAN bus number (1 or 2).
"data_table" (table): Array of byte values {0x00, ..., 0xFF}.
"dlc" (integer): (Optional) explicit DLC override. Defaults to the length of "data_table".
Lua code:
-- Style 1: build once with can.frame(), modify and send repeatedly
local tx = can.frame(0x600, 1, {0,0,0,0,0,0,0,0})
while true do
tx.data[0] = ecu.get(RTDATA.RPM) >> 8
tx.data[1] = ecu.get(RTDATA.RPM) & 0xFF
can.send(tx)
time.delay(50)
end
-- Style 2: send inline without creating a frame object
can.send(0x600, 1, {0x01, 0x02, 0x03})
-- Check if transmission was accepted
if not can.send(0x600, 1, {0xFF}) then
print("TX buffer full!")
end
Note: Use can.frame() when you want to pre-build a frame once and reuse it in a loop, modifying individual bytes between sends.
CAN frame objects (returned by can.recv() or created by can.frame()) have readable and writable fields:
Field |
Read |
Write |
Type |
Range/notes |
YES |
YES |
integer |
0 - 0x1FFFFFFF |
|
.bus |
YES |
YES |
integer |
1-2 |
.dlc |
YES |
YES |
integer |
0-8 |
YES |
NO* |
object |
0-indexed byte access |
*The `.data` field itself cannot be reassigned, but individual bytes can be read and written.
Lua code:
frame.data[0] = 0xFF - write byte 0
local b = frame.data[3] - read byte 3
#frame.data returns the DLC.
tostring(frame) gives a debug representation like: CAN(bus=1 id=0x321 dlc=8 data=[0x01 0x02 ...]).
Lua code:
-- Print frame length (DLC)
local frame = can.frame(0x321, 1, {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08})
print(#frame.data) -- 8
-- Print full debug representation
print(tostring(frame)) -- CAN(bus=1 id=0x321 dlc=8 data=[0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08])
-- Useful for debugging incoming frames
while can.count() > 0 do
local rx = can.recv()
print(tostring(rx))
end
For more information about the MaxxECU user scripts, see User Scripts (LUA), or directly reference the LUA api reference and LUA examples. For more all available LUA settings and options, see Script Code, Script Input Control, Output Functions and Script RT values.