Lua 模块参考

Ameba-Claw 的 Lua 运行时提供两类内置扩展库:驱动层模块lua_driver_*)直接封装片上外设;应用层模块lua_module_*)提供系统服务与高级功能。所有模块均通过标准 require() 加载,无需手动链接。

运行环境

Lua 运行时有两个独立环境:

  • Skill 沙箱:执行 Skill 脚本时的受限环境。ioosdebug 等标准库以及 loadloadfiledofilerawgetrawsetrawequalrawlen 等函数被移除。可用标准库:basepackagecoroutinetablestringutf8math

  • REPL 环境:通过 AT+CLAW=lua 进入的交互式环境,无沙箱限制,可访问全部模块。

下表汇总各模块的可用范围:

模块

功能摘要

Skill

REPL

gpio

引脚输入/输出/中断回调

i2c

I2C 主从通信

spi

SPI 主从传输

rtc

硬件实时时钟

display

屏幕绘图(矢量 + 文字)

audio

录音与播放

cap

Capability 调用桥接

cjson

JSON 解析与序列化

sys

系统时间与延时

file

VFS 文件读写

timer

软件定时器(后台执行代码)

udp

UDP 数据包收发

event

向 Agent 消息总线发布事件

button

事件驱动式按键检测

usb_msc

USB 大容量存储文件读写

usb_uvc

USB UVC 摄像头帧采集

uart

UART 串口收发

pwm

PWM 波形输出

lcdc

LCD 控制器底层操作

touch

GT911 触摸屏事件

basictimer

硬件精确计时(微秒级)

led_strip

WS2812 可编程 LED 灯带

environmental_sensor

DHT11 温湿度传感器

adc

模拟量电压采集(单次/连续)

captouch

片内电容触摸按键检测

ir

红外原始波形发送/接收

thermal

片内硬件温度监测

wifi

Wi-Fi 接入点连接管理

驱动层模块

驱动层模块封装片上外设的硬件寄存器操作,提供 Lua 可直接调用的外设访问接口。

gpio

控制通用输入/输出引脚,支持读写电平、配置上下拉电阻,以及注册边沿中断回调。

函数

说明

gpio.set_direction(pin, dir)

配置方向;dir: "in""out"

gpio.set_level(pin, val)

写入电平;val: 01

gpio.get_level(pin)

读取当前引脚电平

gpio.set_pull(pin, pull)

上下拉;pull: "up""down""none"

gpio.set_irq(pin, edge)

配置中断触发沿;edge: "rise""fall""both"

gpio.irq_enable(pin)

使能引脚中断

gpio.irq_disable(pin)

禁止引脚中断

gpio.on(pin, fn)

注册中断回调函数

gpio.off(pin)

取消回调注册

gpio.dispatch()

处理积压的中断事件,需在主循环中调用

local gpio = require("gpio")

-- 输出模式:驱动 LED
gpio.set_direction("PA_22", "out")
gpio.set_level("PA_22", 1)

-- 输入模式:读取按键状态
gpio.set_direction("PB_5", "in")
gpio.set_pull("PB_5", "up")
local level = gpio.get_level("PB_5")

-- 边沿中断回调
gpio.set_irq("PB_5", "fall")
gpio.irq_enable("PB_5")
gpio.on("PB_5", function(pin) print(pin .. " triggered") end)

i2c

以主设备(Master)身份访问 I2C 总线,支持总线扫描、单字节及块读写,同一总线可挂多个设备句柄。

函数

说明

i2c.bus()

获取 I2C 总线句柄(内部引用计数,可多次调用)

bus:scan()

返回总线上所有响应设备的 7 位地址列表

bus:device(addr)

创建指向指定地址的设备句柄;addr 为 7 位整数

bus:close()

释放总线(引用归零时才反初始化)

device:read(len)

从设备读取 len 字节

device:read_byte()

读取单字节(0–255)

device:write(data)

向设备写入字符串数据

device:write_byte(val)

写入单字节

device:close()

释放设备句柄

local i2c = require("i2c")

local bus = i2c.bus()
-- 扫描总线设备地址
for _, a in ipairs(bus:scan()) do
    print(string.format("found: 0x%02X", a))
end

-- 读取 BMP280 寄存器 0xD0(芯片 ID)
local dev = bus:device(0x76)
dev:write_byte(0xD0)
local chip_id = dev:read_byte()
dev:close()
bus:close()

spi

以主设备身份进行 SPI 全双工数据传输,支持轮询、中断和 DMA 三种传输模式。

函数

说明

spi.new(config)

创建 SPI 主设备句柄;config: {pin_clk, pin_mosi, pin_miso, cpol, cpha, div}

handle:write(data)

轮询写入字符串,返回实际写入字节数

handle:read(len)

轮询读取 len 字节

handle:write_dma(data)

DMA 异步写入

handle:read_dma(len)

DMA 异步读取

handle:close()

释放句柄

local spi = require("spi")

local s = spi.new({
    pin_clk  = "PB_18",
    pin_mosi = "PB_19",
    pin_miso = "PB_20",
    cpol = 0,
    cpha = 0,
    div  = 4,
})
s:write("\x9F")          -- JEDEC ID 命令
local id = s:read(3)
s:close()

uart

访问硬件 UART 串口,支持按长度或按行读取,可设定超时时间。

函数

说明

uart.new(port, tx, rx, baud[, opt])

创建串口句柄;port: 0–3;opt: {data_bits, parity, stop_bits}

handle:write(data)

写入字符串或字节数组,返回实际写入字节数

handle:read(len[, timeout_ms])

读取最多 len 字节;timeout 内返回已收到的数据

handle:read_line([max[, timeout_ms]])

按行读取(遇换行或超时返回)

handle:available()

返回 RX FIFO 中可读字节数

handle:flush_input()

清空 RX 缓冲区

handle:close()

释放串口

local uart = require("uart")

local u = uart.new(1, "PB_2", "PB_3", 115200)
u:write("AT\r\n")
local resp = u:read_line(256, 1000)   -- 最多等待 1 秒
print(resp)
u:close()

pwm

通过硬件定时器(TIM4–TIM7)输出 PWM 波形,每个定时器最多支持 4 个通道,可独立调节占空比。

函数

说明

pwm.new(config)

创建 PWM 句柄;config: {pin, timer_idx, channel, frequency_hz, duty_percent}

handle:set_enabled(bool)

开启或关闭 PWM 输出

handle:set_duty(percent)

设置占空比,范围 0.0–100.0

handle:set_frequency(hz)

修改频率(仅在该定时器只有一个通道时允许)

handle:close()

释放句柄

local pwm = require("pwm")
local sys = require("sys")

local p = pwm.new({
    pin          = "PB_5",
    timer_idx    = 4,
    channel      = 0,
    frequency_hz = 1000,
    duty_percent = 50.0,
})
p:set_enabled(true)
-- 呼吸灯渐亮
for i = 0, 100, 5 do
    p:set_duty(i)
    sys.sleep_ms(30)
end
p:close()

rtc

读取和设置芯片内置的实时时钟,支持每日定时报警和周期性唤醒。

函数

说明

rtc.init()

初始化 RTC(幂等,可多次调用)

rtc.set_time(y, mo, d, h, mi, s)

设置当前时间

rtc.get_time()

返回 {year, mon, mday, hour, min, sec, yday}

rtc.get_local_time(offset_h)

应用时区偏移后返回本地时间

rtc.set_alarm(h, mi, s)

设置每日定时报警(H:M:S)

rtc.alarm_fired()

检查报警是否已触发

rtc.clear_alarm()

清除报警标志

rtc.set_wakeup(seconds)

设置周期性唤醒(1–131072 秒)

rtc.wakeup_fired()

检查周期唤醒是否已触发

rtc.disable_alarm()

取消报警

rtc.disable_wakeup()

取消周期唤醒

local rtc = require("rtc")

rtc.init()
rtc.set_time(2025, 1, 1, 8, 0, 0)
local t = rtc.get_local_time(8)   -- UTC+8
print(string.format("%04d-%02d-%02d %02d:%02d:%02d",
    t.year, t.mon, t.mday, t.hour, t.min, t.sec))

audio

录制 PCM 音频数据(DMIC 输入)或播放音频(I2S 输出),支持 WAV 文件操作和流式 PCM 读写。

函数

说明

audio.new_input(rate, ch, bits)

创建录音句柄;rate: 采样率 Hz;ch: 1 或 2;bits: 8/16/32

audio.new_output(rate, ch, bits)

创建播放句柄

audio.record_wav(file, ms)

录制 ms 毫秒并保存为 WAV 文件到 VFS

audio.play_wav(file)

播放 VFS 中的 WAV 文件

audio.play_tone(freq, ms)

播放指定频率的纯音(Hz,持续 ms 毫秒)

audio.set_gain(dir, val)

设置增益;dir: "input""output";val: 0–15

handle:start_record()

开始录音

handle:read_chunk(bytes)

读取一段 PCM 数据(最大 4096 字节)

handle:stop_record()

停止录音

handle:write_chunk_play(data)

写入 PCM 数据进行播放,返回实际写入字节数

local audio = require("audio")

-- 录制 5 秒并保存为 WAV
audio.record_wav("vfs:/tmp/rec.wav", 5000)
-- 回放
audio.play_wav("vfs:/tmp/rec.wav")

touch

读取 GT911 电容触摸屏的触摸事件,返回坐标和动作类型,需在 board.json 中配置对应设备 ID。

函数

说明

touch.init(device_id)

初始化 GT911;device_id 对应 board.json 中的设备标识

touch.get_event()

非阻塞拉取一个事件 {type, x, y, dx, dy};队列为空返回 nil

touch.width()

触摸面板宽度(像素)

touch.height()

触摸面板高度(像素)

touch.deinit()

停止读取任务并释放资源

事件 type 取值:"down"(按下)、"move"(移动)、"up"(抬起)。

lcdc

直接操作 LCD 控制器(LCDC),支持 RGB 连续扫描和 MCU 命令/数据两种模式。对于大多数绘图需求,建议使用更高层的 display 模块。

函数

说明

lcdc.rgb_init(config)

初始化 RGB 模式;config: {width, height, hsync_pulse, vsync_pulse, ...}

lcdc.mcu_init(config)

初始化 MCU 模式

lcdc.mcu_io_write_cmd(cmd)

发送命令字节

lcdc.mcu_io_write_data(data)

写入显示数据

lcdc.mcu_dma_start(addr, len)

启动 DMA 将数据搬运至显示屏

lcdc.enable()

使能显示输出

lcdc.update()

触发帧更新

lcdc.deinit()

关闭 LCD 控制器

adc

从支持 ADC 功能的 GPIO 引脚读取模拟电压。硬件为单实例,同时仅允许一个句柄打开;支持软件触发("sw",默认)和自动扫描("auto")两种模式。

函数

说明

adc.new(pin1[, pin2, ...][, mode])

打开 1–12 个 ADC 通道;mode: "sw"``(默认)或 ``"auto"

handle:read()

(SW 模式)触发单次采样,返回 {[ch_id]=mV, ...}

handle:trigger([enable])

(SW 模式)启动/停止连续转换;不带参数或 true 启动,false 停止

handle:readable()

(SW 模式)FIFO 中是否有待读样本

handle:read_raw()

(SW 模式)从 FIFO 弹出一条原始计数值;FIFO 空时返回 nil

handle:read_auto(count)

(AUTO 模式)采集 count 个样本(1–256),返回 {ch=N, mv=N} 数组

handle:close()

释放通道,引脚恢复 GPIO 模式

local adc = require("adc")
local sys = require("sys")

-- 软件触发单引脚采样
local ch = adc.new("PA_13")
for i = 1, 5 do
    local r = ch:read()
    print(string.format("sample %d: %d mV", i, r[6]))
    sys.sleep_ms(200)
end
ch:close()

-- 自动模式:双通道 8 次采样
local ch2 = adc.new("PA_13", "PA_14", "auto")
local results = ch2:read_auto(8)
for _, r in ipairs(results) do
    print(string.format("ch=%d  %d mV", r.ch, r.mv))
end
ch2:close()

captouch

读取片上 CapTouch 控制器的电容触摸按键状态,轮询模式,不注册中断。适用于芯片内置触摸引脚(PA_16–PA_24 等),与外接 GT911 面板的 touch 模块无关。

备注

captouch.new() 后需等待约 500–1000 ms,让硬件 ETC 基线自校准完成再读取数据。

函数

说明

captouch.new(pin1[, pin2, ...][, opts])

打开电容触摸按键;opts: {threshold, mbias, n_noise_thr, p_noise_thr, interval_ms, ch_mbias, name}

handle:read()

返回 {count, any_pressed, pressed_count, keys={...}};每个 key 项含 {index, channel, pin, pressed, smooth, benchmark, delta, threshold}

handle:is_pressed(idx)

检查第 idx 个按键(1-based)是否被按下

handle:name()

返回设备名称

handle:close()

释放句柄

local captouch = require("captouch")
local sys      = require("sys")

local dev = captouch.new("PA_20")
sys.sleep_ms(1000)   -- 等待基线稳定
for i = 1, 20 do
    local s = dev:read()
    local k = s.keys[1]
    print(string.format("smooth=%d baseline=%d delta=%d pressed=%s",
        k.smooth, k.benchmark, k.delta, tostring(k.pressed)))
    sys.sleep_ms(100)
end
dev:close()

ir

发送或接收红外原始波形(符号数组)。TX 和 RX 共用同一硬件外设,不可同时使用;载波频率可配置,默认 38 kHz。NEC 等协议编解码需由调用方在 Lua 层实现。

函数

说明

ir.new(tx_pin, rx_pin[, opts])

打开 IR 外设;tx_pin/rx_pin 可传 nil(仅启用一个方向);opts: {carrier_hz=38000}

handle:send_raw(symbols[, mode])

发送原始波形;symbols: {level=0|1, duration_us=N} 数组;mode: "poll"(默认,CPU 占用)或 "intr"(ISR 填充,CPU 释放)

handle:receive([timeout_ms])

接收原始帧;成功返回符号数组,超时返回 nil, "timeout";默认等待 5000 ms

handle:info()

返回 {carrier_hz, tx_pin, rx_pin}

handle:close()

释放硬件

local ir = require("ir")

-- 发送(轮询模式)
local tx = ir.new("PA_25", nil)
local syms = {}
-- 以 NEC 协议填充 syms 后调用 send_raw
tx:send_raw(syms, "poll")
tx:close()

-- 接收(等待 10 秒)
local rx = ir.new(nil, "PA_26")
local frames, err = rx:receive(10000)
if frames then
    for i, s in ipairs(frames) do
        print(i, s.level, s.duration_us)
    end
else
    print("no signal:", err)
end
rx:close()

thermal

读取片内硬件温度传感器(Thermal Monitor),支持查询当前温度、历史峰值及上电温度,支持摄氏度和华氏度输出。

函数

说明

thermal.new()

初始化温度传感器(引用计数,可多次调用)

handle:read()

当前温度(摄氏度)

handle:read_f()

当前温度(华氏度)

handle:max_temp()

自上次 clear_max() 后记录到的最高温度(℃)

handle:min_temp()

自上次 clear_min() 后记录到的最低温度(℃)

handle:power_on_temp()

上电时记录的温度(℃)

handle:clear_max()

清除最高温度记录

handle:clear_min()

清除最低温度记录

handle:close()

释放句柄(引用归零时关闭硬件时钟)

local thermal = require("thermal")
local sys     = require("sys")

local t = thermal.new()
for i = 1, 5 do
    print(string.format("temp: %.1f °C", t:read()))
    sys.sleep_ms(1000)
end
print("max:", t:max_temp(), "  min:", t:min_temp())
t:close()

usb_msc

通过 USB 主机接口访问大容量存储设备(U 盘),提供文件读写、目录列举和路径删除操作。标准调用顺序为 initwait_readymount → 文件操作 → umountdeinit

备注

usb_mscusb_uvc 共用 USB 主机控制器,同一时刻只能有一个处于活跃状态。

函数

说明

usb_msc.init()

初始化 USB 主机及 MSC 类驱动

usb_msc.wait_ready([ms])

等待设备枚举完成;默认超时 10000 ms

usb_msc.mount()

挂载文件系统,返回盘符(如 "0:"

usb_msc.umount()

卸载文件系统

usb_msc.deinit()

停止 USB 主机

usb_msc.write_file(path, data)

写入文件;文件不存在则创建

usb_msc.read_file(path)

读取文件全部内容

usb_msc.list_dir([path])

返回条目数组,每条含 {name, size, is_dir}

usb_msc.remove(path)

删除文件或目录

local msc = require("usb_msc")

msc.init()
local ok, err = msc.wait_ready(10000)
if not ok then error(err) end

local drive = msc.mount()
msc.write_file(drive .. "hello.txt", "Hello USB!")
local data = msc.read_file(drive .. "hello.txt")
print(data)

for _, e in ipairs(msc.list_dir(drive)) do
    print(e.name, e.size, e.is_dir)
end
msc.umount()
msc.deinit()

usb_uvc

通过 USB 主机接口采集 UVC 摄像头帧数据,支持 MJPEG、YUV 和 H.264 格式,提供流参数配置、启停和逐帧读取接口。

备注

usb_uvcusb_msc 共用 USB 主机控制器,同一时刻只能有一个处于活跃状态。

函数

说明

usb_uvc.init()

初始化 USB 主机及 UVC 类驱动

usb_uvc.wait_ready([timeout_ms])

等待摄像头枚举完成;默认超时 10000 ms

usb_uvc.set_param(opts)

配置流参数;opts: {width=640, height=480, fps=15, format="mjpeg", buf_size=153600};format: "mjpeg""yuv""h264"

usb_uvc.stream_on()

开启视频流

usb_uvc.get_frame([timeout_ms])

获取一帧原始数据;默认超时 1000 ms

usb_uvc.stream_off()

停止视频流

usb_uvc.deinit()

停止 USB 主机

local uvc  = require("usb_uvc")
local file = require("file")

uvc.init()
uvc.wait_ready(10000)
uvc.set_param({width=640, height=480, fps=15, format="mjpeg"})
uvc.stream_on()

local frame, err = uvc.get_frame(2000)
if frame then
    file.write("vfs:/tmp/frame.jpg", frame)
    print("frame size:", #frame)
else
    print("no frame:", err)
end

uvc.stream_off()
uvc.deinit()

高级应用模块

高级应用模块提供系统服务、通信协议和高级功能,大多数可在 Skill 沙箱中使用。

cap

在 Skill 脚本内部调用已注册的 C 层 Capability,以 JSON 字符串传递参数并接收结果。

函数

说明

cap.call(name[, json])

调用 Capability;返回 (ok, result_json)

cap.list()

返回所有已注册 Capability 的 JSON 目录

cap.call 始终返回两个值,必须同时捕获:

local cap   = require("cap")
local cjson = require("cjson")

-- 正确:同时接收状态和结果
local ok, result = cap.call("get_weather", '{"city":"Beijing"}')
if not ok then
    return '{"error":' .. cjson.encode(result) .. '}'
end
local data = cjson.decode(result)

警告

只写 local result = cap.call(...) 时,result 实际持有布尔状态值,JSON 结果被丢弃。

sys

查询设备运行时间和执行毫秒级延时,所有时间从设备上电时刻开始计数。

函数

说明

sys.millis()

单调毫秒计数(约 49 天溢出归零;不是 Unix 时间戳)

sys.uptime()

设备启动后经过的秒数

sys.sleep_ms(ms)

阻塞等待 ms 毫秒

local sys = require("sys")

local t0 = sys.millis()
sys.sleep_ms(1000)
print("elapsed:", sys.millis() - t0, "ms")

备注

sys 没有 Unix 时间戳函数。需要日历时间请使用 rtc 模块;Skill 沙箱中无法使用 os.time()

cjson

JSON 数据的编解码,支持嵌套对象、数组和所有 JSON 基本类型。

函数

说明

cjson.decode(str)

将 JSON 字符串解析为 Lua table 或基本类型

cjson.encode(val)

将 Lua 值序列化为紧凑 JSON;自动区分数组和对象

local cjson = require("cjson")

local obj = cjson.decode('{"x":1,"y":[2,3]}')
print(obj.x, obj.y[1])                       -- 1  2

local s = cjson.encode({status="ok", code=200})
print(s)                                      -- {"status":"ok","code":200}

file

读写 vfs:/ 路径下的文件,路径中未包含 vfs: 前缀时自动补全。

函数

说明

file.list()

返回 {name=size, ...} 格式的文件列表

file.exists(name)

判断文件是否存在

file.read(name)

读取文件全部内容(二进制安全)

file.write(name, data)

写入二进制数据;文件不存在则创建

file.remove(name)

删除文件

file.rename(old, new)

重命名文件

file.run(name)

加载并执行脚本,返回脚本的返回值

local file = require("file")

file.write("vfs:/tmp/hello.txt", "Hello, Ameba!")
local content = file.read("vfs:/tmp/hello.txt")
print(content)

for name, size in pairs(file.list()) do
    print(name, size)
end

timer

在后台运行 Lua 代码片段的软件定时器,最多同时运行 8 个,回调超时保护为 5 秒。

函数

说明

timer.start(ms, code, repeat)

启动定时器;ms: 间隔毫秒;code: Lua 代码字符串;repeat: 是否重复;返回 id

timer.stop(id)

按 id 停止定时器

timer.list()

返回所有活跃定时器的信息数组

local timer = require("timer")

-- 每 2 秒打印一次(重复执行)
local id = timer.start(2000, [[
    local sys = require("sys")
    print("tick:", sys.uptime())
]], true)

require("sys").sleep_ms(10000)
timer.stop(id)

udp

收发 UDP 数据包,适合局域网内设备间的低延迟通信。

函数

说明

udp.open(host, port)

创建已连接的 UDP socket

udp.send(fd, data)

向已连接的目标发送数据

udp.bind(port)

创建监听 socket

udp.recv(fd[, max[, timeout_ms]])

接收数据包;timeout: -1 无限等待,0 不阻塞,>0 毫秒

udp.close(fd)

关闭 socket

local udp = require("udp")

-- 发送
local tx = udp.open("192.168.1.100", 9000)
udp.send(tx, "hello")
udp.close(tx)

-- 接收(超时 500ms)
local rx = udp.bind(9000)
local data, from_ip = udp.recv(rx, 1024, 500)
if data then print(from_ip, data) end
udp.close(rx)

event

向 Agent 消息总线发布事件,Skill 可借此主动推送通知或触发自定义事件流程。

函数

说明

event.publish_message(src, channel, chat_id, text[, sender])

发布一条消息事件;src 为 Capability 名称,text 为消息正文

event.publish_trigger(src, type, key[, payload])

发布触发器事件;payload 为可选 JSON 字符串

event.wait([timeout_ms])

阻塞等待 GPIO 事件;nil 表示超时

local event = require("event")

event.publish_message("my_skill", "default", "123", "传感器温度超限!")

button

事件驱动式按键检测,对 gpio 中断的高层封装,支持单击、双击、长按等语义事件,并提供非阻塞事件队列轮询接口。

函数

说明

button.on(pin, event, fn)

注册按键语义回调;event: "down""up""click""double""long_press""hold"

button.off(pin)

取消该引脚的所有回调

button.get_event()

非阻塞拉取一个事件 {pin, type, timestamp};队列空时返回 nil

button.get_level(pin)

读取当前按键电平

button.flush()

清空待处理事件队列

button.dispatch()

处理积压的按键事件,需在主循环中调用

local button = require("button")
local sys    = require("sys")

-- 注册单击回调
button.on("PB_5", "click", function(pin)
    print(pin .. " clicked")
end)

-- 主循环中处理事件
for _ = 1, 100 do
    button.dispatch()
    sys.sleep_ms(10)
end
button.off("PB_5")

display

在屏幕上绘制图形、文字和像素,提供矢量图形(抗锯齿)和快速路径两套绘图 API,通过 present() 将帧缓冲推送到面板。

初始化与帧控制

函数

说明

display.init(device_id)

初始化显示屏(device_id 来自 board.json)

display.deinit()

释放显示资源

display.backlight(on)

控制背光开关

display.begin_frame([opt])

开始新帧;opt: {clear=true, color=0xRRGGBB}

display.present()

将帧缓冲刷新到屏幕

display.width

屏幕宽度(只读属性)

display.height

屏幕高度(只读属性)

基础绘图

函数

说明

display.clear(color)

全屏填充纯色(0xRRGGBB)

display.fill_rect(x, y, w, h, color)

填充矩形

display.draw_pixel(x, y, color)

绘制单像素

display.draw_line(x0, y0, x1, y1, color[, w])

画线;w 为可选线宽

display.draw_rect(x, y, w, h, color[, thick])

矩形边框;thick 为线宽

display.fill_round_rect(x, y, w, h, r, color)

填充圆角矩形

display.draw_circle(cx, cy, r, color[, w])

圆形边框

display.fill_circles(tbl)

批量填充圆;tbl: {cx, cy, r, color, ...}

display.draw_arc(cx, cy, r, s, e, color[, w])

圆弧;s/e 为起止角度(度)

display.fill_triangle(x0, y0, x1, y1, x2, y2, color)

填充三角形

文字

函数

说明

display.draw_text(x, y, str, fg[, bg[, px]])

绘制文本;px 字号可选 14/20/24/26

display.draw_text_aligned(x, y, w, h, str, fg[, align])

在矩形框内对齐文本;align: "left""center""right"

display.measure_text(str[, px])

测量文本所占像素尺寸

像素块

函数

说明

display.draw_pixels(x, y, w, h, buf, fmt)

贴图;buf 为 RGB565 原始数据字符串;fmt: "rgb565"

display.set_clip_rect(x, y, w, h)

设置裁剪区域

display.clear_clip_rect()

取消裁剪

local display = require("display")

display.init("lcd_0")
display.backlight(true)
display.begin_frame({clear=true, color=0x000000})
display.fill_round_rect(20, 20, 200, 60, 10, 0x1E90FF)
display.draw_text(30, 35, "Hello Ameba!", 0xFFFFFF, nil, 20)
display.present()

led_strip

驱动 WS2812/WS2812B 可编程 LED 灯带,通过 SPI 接口以波形编码方式输出控制信号,每颗灯颜色独立可控。

函数

说明

led_strip.new(config)

创建灯带句柄;config: {spi=0|1, mosi="PIN", count=N}

led_strip.stop_requested()

检查是否收到停止指令(AT+CLAW=led,off

handle:set_pixel(i, r, g, b)

设置第 i 颗灯颜色(1-based);RGB 各 0–255

handle:set_pixel_hsv(i, h, s, v)

用 HSV 设置;h: 0–359;s/v: 0–255

handle:fill(r, g, b)

将所有灯设为同一 RGB 颜色

handle:fill_hsv(h, s, v)

将所有灯设为同一 HSV 颜色

handle:clear()

熄灭所有灯

handle:show()

将颜色数据通过 DMA 推送到灯带

handle:close()

释放句柄

local led = require("led_strip")
local sys = require("sys")

local strip = led.new({spi=0, mosi="PB_8", count=30})
for offset = 0, 359 do
    if led.stop_requested() then break end
    for i = 1, 30 do
        strip:set_pixel_hsv(i, (offset + i * 12) % 360, 255, 180)
    end
    strip:show()
    sys.sleep_ms(20)
end
strip:close()

environmental_sensor

读取 DHT11 温湿度传感器的数据,通过单总线协议采集温度和相对湿度,含校验和验证。

函数

说明

environmental_sensor.new({pin="PB_8"})

创建 DHT11 句柄;pin 为数据引脚

handle:read()

返回 {temperature=°C, humidity=%}

handle:read_temperature()

温度(摄氏度)

handle:read_humidity()

相对湿度(%)

handle:name()

返回传感器型号字符串

handle:close()

释放句柄

local env = require("environmental_sensor")

local s = env.new({pin="PB_8"})
local data = s:read()
print(string.format("%.1f°C  %.1f%%RH", data.temperature, data.humidity))
s:close()

basictimer

基于硬件定时器(TIM0–TIM3)的高精度计时工具,精度可达微秒级,适合测量精确时间间隔。

函数

说明

basictimer.new(idx, period_us[, clk[, div]])

创建定时器;idx: 0–3;clk: "sdm32k"``(默认)或 ``"xtal"

handle:start()

启动计数

handle:stop()

停止计数

handle:get_count()

读取当前计数寄存器值

handle:get_irq_count()

读取中断触发次数

handle:clear_irq_count()

清零中断计数

handle:set_period(us)

修改计时周期(微秒)

handle:close()

释放硬件定时器

local bt  = require("basictimer")
local sys = require("sys")

local t = bt.new(0, 1000)   -- TIM0,周期 1000μs
t:start()
sys.sleep_ms(100)
print("IRQ count:", t:get_irq_count())   -- ≈ 100
t:stop()
t:close()

wifi

连接 Wi-Fi 接入点并查询连接状态,调用过程含 DHCP 等待,为阻塞操作,仅 REPL 环境可用。

函数

说明

wifi.connect(ssid, password)

连接 AP 并等待 DHCP;成功返回 true

wifi.status()

返回当前是否处于已连接状态

local wifi = require("wifi")

local ok = wifi.connect("MySSID", "MyPassword")
if ok then print("Wi-Fi connected") end

编写 Skill 脚本

入口函数

每个 Skill 脚本必须定义名为 run 的入口函数,Agent 调用 Skill 时将调用此函数并传入参数:

function run(args)
    -- args 是已解码的 Lua table,可直接访问字段
    -- 返回值必须是 JSON 字符串
    return '{"status":"ok"}'
end

备注

args 是已解码的 Lua table,不是 JSON 字符串,可直接访问字段,如 args.pinargs.times。返回值必须是 JSON 字符串,Agent 将其作为工具调用结果解析。

文件路径约定

路径

用途

vfs:/tmp/<name>.lua

临时脚本,重启后自动清除,适合测试

vfs:/scripts/<name>.lua

持久化用户脚本,重启后保留;不受 Skill 目录管理

vfs:/skills/<name>/scripts/main.lua

Agent 可调用的 Skill;必须位于此路径才能被注册

Lua 5.4 位运算

Ameba-Claw 使用 Lua 5.4,不加载 bit 模块,请使用原生运算符:

运算

正确写法

错误写法(Lua 5.1 风格)

按位与

a & b

bit.band(a, b)

按位或

a | b

bit.bor(a, b)

按位异或

a ~ b

bit.bxor(a, b)

右移

a >> n

bit.rshift(a, n)

左移

a << n

bit.lshift(a, n)

系统时间与延时

sys 模块提供从设备上电起的单调计数,不提供 Unix 时间戳:

local sys = require("sys")

local ms = sys.millis()   -- 单调毫秒计数(不是 Unix 时间戳)
local up = sys.uptime()   -- 启动后秒数(浮点),可用于超时判断
sys.sleep_ms(500)         -- 阻塞等待 500 毫秒

备注

sys.millis()sys.uptime() 均从上电时刻开始计数,不代表现实时间,断电重启后归零。如需日历时间,请使用 rtc 模块。

完整示例:GPIO 闪烁 LED

以下是控制 PA_22 引脚做 LED 闪烁的完整 Skill 脚本:

local gpio = require("gpio")
local sys  = require("sys")

function run(args)
    local pin   = args.pin   or "PA_22"
    local times = args.times or 6

    gpio.set_direction(pin, "out")

    for i = 1, times do
        gpio.set_level(pin, i % 2)
        sys.sleep_ms(500)
    end

    gpio.set_direction(pin, "in")
    return '{"status":"ok"}'
end

将此文件保存至 vfs:/skills/blink_led/scripts/main.lua 后,通过 AT 命令调用:

AT+CLAW=skill,blink_led
AT+CLAW=skill,blink_led,{"pin":"PA_22","times":10}