326 lines
7.6 KiB
Lua
326 lines
7.6 KiB
Lua
-- ADS1115模数转换器 硬件脚本(测试)
|
||
|
||
|
||
-- 这个函数是辅助用的,它能够打印一张表出来
|
||
function print_table(t, indent)
|
||
indent = indent or 0
|
||
for k, v in pairs(t) do
|
||
if type(v) == 'table' then
|
||
print(string.rep(' ', indent) .. k .. ":")
|
||
print_table(v, indent + 2)
|
||
else
|
||
print(string.rep(' ', indent) .. k .. ": " .. tostring(v))
|
||
end
|
||
end
|
||
end
|
||
|
||
ADS1115_ADDR = 0x48 -- ADS1115的I2C地址
|
||
ADS1115_REG_CONVERSION = 0x00 -- 转换结果(只读)
|
||
ADS1115_REG_CONFIG = 0x01 -- 配置寄存器(读/写)
|
||
ADS1115_REG_LO_THRESH = 0x02 -- 低阈值比较
|
||
ADS1115_REG_HI_THRESH = 0x03 -- 高阈值比较
|
||
-- ====================================
|
||
-- ADS1115 配置寄存器 bit 定义(16位)
|
||
-- ====================================
|
||
-- BIT15: OS[0] => 单次转换启动位(1=开始)
|
||
-- BIT14-12: MUX[2:0] => 输入多路选择
|
||
-- BIT11-9: PGA[2:0] => 可编程增益放大器
|
||
-- BIT8: MODE => 0=连续转换,1=单次(省电)
|
||
-- BIT7-5: DR[2:0] => 数据速率
|
||
-- BIT4: COMP_MODE => 比较模式(0=传统)
|
||
-- BIT3: COMP_POL => 比较极性(0=低有效)
|
||
-- BIT2: COMP_LAT => 比较锁存(0=不锁存)
|
||
-- BIT1-0: COMP_QUE => 比较器队列(11=禁用)
|
||
--
|
||
-- ==== MUX 输入通道 ====
|
||
ADS1115_MUX_AIN0_AIN1 = 0x0000 -- 差分:P=AIN0,N=AIN1(默认)
|
||
ADS1115_MUX_AIN0_AIN3 = 0x1000 -- 差分:P=AIN0,N=AIN3
|
||
ADS1115_MUX_AIN1_AIN3 = 0x2000 -- 差分:P=AIN1,N=AIN3
|
||
ADS1115_MUX_AIN2_AIN3 = 0x3000 -- 差分:P=AIN2,N=AIN3
|
||
ADS1115_MUX_AIN0_GND = 0x4000 -- 单端:AIN0
|
||
ADS1115_MUX_AIN1_GND = 0x5000 -- 单端:AIN1
|
||
ADS1115_MUX_AIN2_GND = 0x6000 -- 单端:AIN2
|
||
ADS1115_MUX_AIN3_GND = 0x7000 -- 单端:AIN3
|
||
|
||
-- ==== PGA 增益(满量程范围)====
|
||
ADS1115_PGA_6_144V = 0x0000 -- ±6.144V (1LSB=0.1875mV)
|
||
ADS1115_PGA_4_096V = 0x0200 -- ±4.096V (1LSB=0.125mV)
|
||
ADS1115_PGA_2_048V = 0x0400 -- ±2.048V (1LSB=0.0625mV)(默认)
|
||
ADS1115_PGA_1_024V = 0x0600 -- ±1.024V (1LSB=0.03125mV)
|
||
ADS1115_PGA_0_512V = 0x0800 -- ±0.512V (1LSB=0.015625mV)
|
||
ADS1115_PGA_0_256V = 0x0A00 -- ±0.256V (1LSB=0.0078125mV)
|
||
|
||
-- ==== 数据速率 ====
|
||
ADS1115_DR_8SPS = 0x0000 -- 8 SPS
|
||
ADS1115_DR_16SPS = 0x0020 -- 16 SPS
|
||
ADS1115_DR_32SPS = 0x0040 -- 32 SPS
|
||
ADS1115_DR_64SPS = 0x0060 -- 64 SPS
|
||
ADS1115_DR_128SPS = 0x0080 -- 128 SPS (默认)
|
||
ADS1115_DR_250SPS = 0x00A0 -- 250 SPS
|
||
ADS1115_DR_475SPS = 0x00C0 -- 475 SPS
|
||
ADS1115_DR_860SPS = 0x00E0 -- 860 SPS
|
||
|
||
-- ==== 比较器队列(COMP_QUE)====
|
||
ADS1115_COMP_QUE_1 = 0x0000 -- 1次后触发
|
||
ADS1115_COMP_QUE_2 = 0x0001 -- 2次后触发
|
||
ADS1115_COMP_QUE_4 = 0x0002 -- 4次后触发
|
||
ADS1115_COMP_QUE_DISABLE = 0x0003 -- 禁用比较器(默认)
|
||
|
||
-- ==== 操作模式 ====
|
||
ADS1115_MODE_CONTINUOUS = 0x0000 -- 连续转换
|
||
ADS1115_MODE_SINGLE = 0x0100 -- 单次转换(默认,省电)
|
||
|
||
-- ==== 启动转换 ====
|
||
ADS1115_OS_START = 0x8000 -- 启动单次转换
|
||
|
||
-- ADS1115 配置上下文
|
||
ads1115_t = {
|
||
addr = 0x00,
|
||
config = 0x00, -- 16bits
|
||
fs_valtage = 0.0 -- 满量程电压(取决于PGA)
|
||
}
|
||
|
||
-- PGA对应的满量程电压(单位:V)
|
||
pga_fs = {
|
||
6.144, -- ADS1115_PGA_6_144V [0]
|
||
4.096, -- ADS1115_PGA_4_096V [1]
|
||
2.048, -- ADS1115_PGA_2_048V [2]
|
||
1.024, -- ADS1115_PGA_1_024V [3]
|
||
0.512, -- ADS1115_PGA_0_512V [4]
|
||
0.256 -- ADS1115_PGA_0_256V [5]
|
||
}
|
||
|
||
-- PGA 增益对应的满量程电压名
|
||
pga_names = {
|
||
"±6.144V", -- [0]
|
||
"±4.096V", -- [1]
|
||
"±2.048V", -- [2]
|
||
"±1.024V", -- [3]
|
||
"±0.512V", -- [4]
|
||
"±0.256V" -- [5]
|
||
}
|
||
|
||
-- 数据速率字符串
|
||
dr_names = {
|
||
"8 SPS", -- [0]
|
||
"16 SPS", -- [1]
|
||
"32 SPS", -- [2]
|
||
"64 SPS", -- [3]
|
||
"128 SPS", -- [4]
|
||
"250 SPS", -- [5]
|
||
"475 SPS", -- [6]
|
||
"860 SPS" -- [7]
|
||
}
|
||
|
||
|
||
|
||
-- I2C写2字节(大端)
|
||
function i2c_write_word(fd, reg, val)
|
||
i2c_write_reg(fd, reg + 0, (val >> 8) | 0xFF)
|
||
i2c_write_reg(fd, reg + 1, val & 0xFF)
|
||
end
|
||
|
||
--
|
||
-- 【配置脚本】
|
||
-- FIXME(20260602-qing): 异常处理
|
||
function build(data)
|
||
|
||
-- 检查该参数是否是一张表
|
||
if type(data) ~= "table" then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Arguments: table"
|
||
}
|
||
end
|
||
|
||
print("-------- Lua builder func get a table --------")
|
||
print_table(data)
|
||
print("----------------------------------------------")
|
||
local fd = data.fd
|
||
|
||
-- 检查文件句柄参数是否存在
|
||
if fd == nil then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Arguments: fd"
|
||
}
|
||
end
|
||
|
||
local addr = data.address
|
||
|
||
-- 检查地址参数是否存在
|
||
if addr == nil then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Arguments: addr"
|
||
}
|
||
end
|
||
|
||
addr = tonumber(addr)
|
||
|
||
-- 写进配置表
|
||
ads1115.addr = addr
|
||
|
||
|
||
-- 开始配置PCA9685
|
||
i2c_set_addr(fd, addr)
|
||
|
||
-- 重启PCA9685
|
||
i2c_write_reg(fd, 0x00, 0x80)
|
||
|
||
-- 等待振荡器启动
|
||
milli_sleep(5)
|
||
|
||
i2c_write_reg(fd, 0x00, 0x10) -- 进入SLEEP模式(允许改频率)
|
||
i2c_write_reg(fd, 0xFE, math.floor(prescale))
|
||
i2c_write_reg(fd, 0x00, 0x20) -- 退出SLEEP模式
|
||
|
||
-- 等待振荡器启动
|
||
milli_sleep(5)
|
||
|
||
-- 返回成功信号
|
||
return {
|
||
result = "OK"
|
||
}
|
||
|
||
end
|
||
|
||
-- 【销毁PCA9685的脚本】
|
||
-- 重置PCA9685
|
||
-- NOTE(20260612-qing): 其实可以不需要,因为我们只是清空设置
|
||
function destroy(data)
|
||
|
||
-- 检查该参数是否是一张表
|
||
if type(data) ~= "table" then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Arguments: table"
|
||
}
|
||
end
|
||
|
||
print("-------- Lua ender func get a table --------")
|
||
print_table(data)
|
||
print("--------------------------------------------")
|
||
|
||
local fd = data.fd
|
||
|
||
-- 检查fd参数是否存在
|
||
if fd == nil then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Arguments: fd"
|
||
}
|
||
end
|
||
|
||
local addr = data.address
|
||
|
||
-- 检查address参数是否存在
|
||
if addr == nil then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Arguments: addr"
|
||
}
|
||
end
|
||
|
||
addr = tonumber(addr)
|
||
|
||
-- 准备配置
|
||
i2c_set_addr(fd, addr)
|
||
|
||
-- 重启PCA9685
|
||
i2c_write_reg(fd, 0x00, 0x80)
|
||
|
||
-- 返回成功信号
|
||
return {
|
||
result = "OK"
|
||
}
|
||
|
||
end
|
||
|
||
|
||
-- 【调用PCA9685】
|
||
-- 将一个舵机通道转动到一个角度
|
||
-- NOTE(20260612-qing): 接收一个参数(表),返回一个结果(表)
|
||
function call(data)
|
||
|
||
-- 检查该参数是否是一张表
|
||
if type(data) ~= "table" then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Arguments: table"
|
||
}
|
||
end
|
||
|
||
print("-------- Lua caller func get a table --------")
|
||
print_table(data)
|
||
print("---------------------------------------------")
|
||
|
||
|
||
local fd = data.fd
|
||
|
||
-- 检查fd参数是否存在
|
||
if fd == nil then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Argument: fd"
|
||
}
|
||
end
|
||
|
||
local addr = data.address
|
||
|
||
-- 检查address参数是否存在
|
||
if addr == nil then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Argument: addr"
|
||
}
|
||
end
|
||
|
||
addr = tonumber(addr)
|
||
|
||
local channel = data.channel
|
||
|
||
-- 检查channel参数是否存在
|
||
if channel == nil then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Argument: channel"
|
||
}
|
||
end
|
||
|
||
local angle = data.angle
|
||
|
||
-- 检查angle参数是否存在
|
||
if angle == nil then
|
||
return {
|
||
result = "ERR",
|
||
message = "Invalid Argument: angle"
|
||
}
|
||
end
|
||
|
||
print(string.format("Lua hardware drive set angle: %d", angle))
|
||
|
||
-- 设置I2C地址
|
||
i2c_set_addr(fd, addr)
|
||
|
||
-- 计算需要的参数
|
||
local min = 0.5 -- 0度对应0.5ms
|
||
local max = 2.5 -- 180度对应2.5ms
|
||
local width = min + (max - min) * (angle / 180.0)
|
||
local offval = math.floor(width * 4096.0 / 20.0)
|
||
local reg = 0x06 + 4 * channel
|
||
|
||
-- 写I2C寄存器
|
||
i2c_write_reg(fd, reg + 0, (0 >> 0) & 0xFF) -- 1 * 8
|
||
i2c_write_reg(fd, reg + 1, (0 >> 8) & 0xFF) -- 2 * 8
|
||
i2c_write_reg(fd, reg + 2, (offval >> 0) & 0xFF) -- 3 * 8
|
||
i2c_write_reg(fd, reg + 3, (offval >> 8) & 0xFF) -- 4 * 8
|
||
|
||
-- 返回字典
|
||
return {
|
||
result = "OK"
|
||
}
|
||
|
||
end
|
||
|