Skip to content

feat(lua): add lua_driver_twai -- TWAI (CAN bus) Lua driver#96

Open
ayyaris wants to merge 1 commit into
espressif:masterfrom
ayyaris:feat/lua-driver-twai
Open

feat(lua): add lua_driver_twai -- TWAI (CAN bus) Lua driver#96
ayyaris wants to merge 1 commit into
espressif:masterfrom
ayyaris:feat/lua-driver-twai

Conversation

@ayyaris

@ayyaris ayyaris commented May 19, 2026

Copy link
Copy Markdown

Summary

Adds lua_driver_twai, a new Lua module that exposes the ESP32 TWAI (Two-Wire Automotive Interface / CAN bus) peripheral to Lua scripts via the ESP-IDF v6 esp_driver_twai node API.

API

local twai = require("twai")

local can = twai.new(tx_gpio, rx_gpio, bitrate [, opts])
-- opts: { listen_only=bool, loopback=bool }

can:enable()
can:disable()
can:send(id, data [, is_extended [, is_rtr]])
local frame = can:receive([timeout_ms])   -- {id, data, extended, rtr} | nil
local st    = can:status()               -- {state, tx_errors, rx_errors, ...}
can:recover()
can:close()

Implementation

  • ISR-driven RX queue (depth 32) via on_rx_done callback — zero-copy path from ISR to FreeRTOS queue
  • Kconfig: APP_CLAW_LUA_DRIVER_TWAI (default y when SOC_TWAI_SUPPORTED)
  • Registration: components/common/app_claw/idf_component.yml conditional dependency + app_lua_modules.c registration
  • Requires esp_driver_twai (IDF v6+)

Files

File Purpose
components/lua_modules/lua_driver_twai/src/lua_driver_twai.c Module implementation
components/lua_modules/lua_driver_twai/src/lua_driver_twai.h Public header
components/lua_modules/lua_driver_twai/CMakeLists.txt Component registration
components/lua_modules/lua_driver_twai/README.md Usage docs + examples
components/common/app_claw/Kconfig APP_CLAW_LUA_DRIVER_TWAI option
components/common/app_claw/app_lua_modules.c Module registration
components/common/app_claw/idf_component.yml Conditional dependency

Test plan

  • Builds without error on ESP32-S3 (SOC_TWAI_SUPPORTED=y)
  • Builds without error on ESP32-C3 / other TWAI-capable chips
  • require("twai") succeeds in Lua runtime
  • twai.new() creates node, enable()/send()/receive() work on bus

🤖 Generated with Claude Code

Wraps the ESP-IDF v6 esp_driver_twai node API as a Lua module:

API (require("twai")):
  twai.new(tx_gpio, rx_gpio, bitrate [, opts])  -> node
  node:enable()
  node:disable()
  node:send(id, data [, is_extended [, is_rtr]])
  node:receive([timeout_ms])     -> {id, data, extended, rtr} | nil
  node:status()                  -> {state, tx_errors, rx_errors, ...}
  node:recover()
  node:close()

Implementation:
- ISR-driven RX queue (depth 32) via on_rx_done callback
- Registered via Kconfig APP_CLAW_LUA_DRIVER_TWAI
  (default y when SOC_TWAI_SUPPORTED)
- idf_component.yml: conditional dependency on lua_driver_twai

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Alessio Ayyari seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new twai Lua module (lua_driver_twai) to expose the ESP32 TWAI (CAN bus) peripheral via ESP-IDF v6’s esp_driver_twai node API, wiring it into app_claw’s Kconfig/dependency system and Lua module registration.

Changes:

  • Adds a new lua_driver_twai component implementing twai.new()/enable()/send()/receive()/status()/recover()/close() with an ISR-driven RX queue.
  • Adds APP_CLAW_LUA_DRIVER_TWAI Kconfig and idf_component.yml conditional dependency, plus registration in app_lua_modules.c.
  • Removes LVGL Lua module configuration/dependency/registration from app_claw (appears unrelated and breaking).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
components/lua_modules/lua_driver_twai/src/lua_driver_twai.c Implements the TWAI Lua driver, including ISR RX callback + Lua API surface.
components/lua_modules/lua_driver_twai/src/lua_driver_twai.h Public header for module open/registration.
components/lua_modules/lua_driver_twai/README.md Documents usage and examples for the twai Lua module.
components/lua_modules/lua_driver_twai/CMakeLists.txt Registers the new component and its dependencies.
components/common/app_claw/Kconfig Adds APP_CLAW_LUA_DRIVER_TWAI option; also removes LVGL option.
components/common/app_claw/idf_component.yml Adds conditional dependency for lua_driver_twai; also removes LVGL dependency block.
components/common/app_claw/app_lua_modules.c Registers the twai module; also removes LVGL include/registration entries.
Comments suppressed due to low confidence (1)

components/common/app_claw/idf_component.yml:272

  • The conditional dependency block for lua_module_lvgl was removed from app_claw’s idf_component.yml, which will prevent the existing lua_module_lvgl component from being pulled in when enabled. If LVGL support is still intended to be available, please re-add the lua_module_lvgl dependency rules/path entry (and keep it aligned with the corresponding Kconfig option).
  lua_module_led_strip:
    rules:
      - if: $CONFIG{APP_CLAW_CAP_LUA} == True
      - if: $CONFIG{APP_CLAW_LUA_MODULE_LED_STRIP} == True
    path: ../../lua_modules/lua_module_led_strip

  lua_module_magnetometer:
    rules:
      - if: $CONFIG{APP_CLAW_CAP_LUA} == True
      - if: $CONFIG{APP_CLAW_LUA_MODULE_MAGNETOMETER} == True
    path: ../../lua_modules/lua_module_magnetometer

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 351 to 360
config APP_CLAW_LUA_MODULE_LED_STRIP
bool "Enable LED strip Lua module"
default y
help
Enable the LED strip Lua module and keep app_claw's direct dependency
on lua_module_led_strip when Lua capability is enabled.

config APP_CLAW_LUA_MODULE_LVGL
bool "Enable LVGL Lua module"
default n
help
Enable the LVGL Lua module and keep app_claw's direct dependency
on lua_module_lvgl when Lua capability is enabled.

config APP_CLAW_LUA_MODULE_MAGNETOMETER
bool "Enable magnetometer Lua module"
default n
Comment on lines 88 to 96
#if CONFIG_APP_CLAW_LUA_MODULE_LCD_TOUCH && defined(CONFIG_ESP_BOARD_DEV_LCD_TOUCH_SUPPORT) && defined(CONFIG_ESP_BOARD_DEV_LCD_TOUCH_SUB_I2C_SUPPORT)
#include "lua_module_lcd_touch.h"
#endif
#if CONFIG_APP_CLAW_LUA_MODULE_LED_STRIP
#include "lua_module_led_strip.h"
#endif
#if CONFIG_APP_CLAW_LUA_MODULE_LVGL
#include "lua_module_lvgl.h"
#endif
#if CONFIG_APP_CLAW_LUA_MODULE_MAGNETOMETER
#include "lua_module_magnetometer.h"
#endif
Comment on lines +86 to +99
int tx_gpio = (int)luaL_checkinteger(L, 1);
int rx_gpio = (int)luaL_checkinteger(L, 2);
uint32_t bps = (uint32_t)luaL_checkinteger(L, 3);

bool listen_only = false;
bool loopback = false;
if (lua_istable(L, 4)) {
lua_getfield(L, 4, "listen_only");
listen_only = lua_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, 4, "loopback");
loopback = lua_toboolean(L, -1);
lua_pop(L, 1);
}
Comment on lines +63 to +67
memcpy(item.data, buf, item.len);

BaseType_t woken = pdFALSE;
xQueueSendFromISR(ud->rx_queue, &item, &woken);
return woken == pdTRUE;
Comment on lines +56 to +64
twai_rx_item_t item = {
.id = frame.header.id,
.is_extended = frame.header.ide,
.is_rtr = frame.header.rtr,
.len = (uint8_t)(frame.header.dlc > LUA_DRIVER_TWAI_DATA_MAX
? LUA_DRIVER_TWAI_DATA_MAX : frame.header.dlc),
};
memcpy(item.data, buf, item.len);


esp_err_t err = twai_node_transmit(ud->node, &frame, pdMS_TO_TICKS(100));
if (err != ESP_OK) {
return luaL_error(L, "twai: transmit failed (%d)", err);
twai_node_record_t record = {0};
esp_err_t err = twai_node_get_info(ud->node, &status, &record);
if (err != ESP_OK) {
return luaL_error(L, "twai: get_info failed (%d)", err);
lua_driver_twai_ud_t *ud = twai_check_ud(L, 1);
esp_err_t err = twai_node_recover(ud->node);
if (err != ESP_OK) {
return luaL_error(L, "twai: recover failed (%d)", err);
Comment on lines +194 to +200
},
.buffer = buf,
.buffer_len = data_len,
};

esp_err_t err = twai_node_transmit(ud->node, &frame, pdMS_TO_TICKS(100));
if (err != ESP_OK) {
Comment on lines +84 to +90
static int twai_new(lua_State *L)
{
int tx_gpio = (int)luaL_checkinteger(L, 1);
int rx_gpio = (int)luaL_checkinteger(L, 2);
uint32_t bps = (uint32_t)luaL_checkinteger(L, 3);

bool listen_only = false;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants