Bläddra i källkod

update:Air8000的adc demo

王城钧 6 månader sedan
förälder
incheckning
d1c4e9dcff

+ 43 - 9
module/Air8000/demo/adc/main.lua

@@ -1,21 +1,55 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.07.15
+@author  王城钧
+@usage
 
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "adcdemo"
-VERSION = "1.0.0"
+本demo演示的功能为:
+1.抽样10个ADC计算值
+2.升序排列后去掉一个最大值和一个最小值,并计算平均值
+3.得到ADC测量值,并通过两种方式打印,一种为特殊通道温度的形式打印,另一种以毫伏的方式打印
+]]
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
 
-log.info("main", PROJECT, VERSION)
+PROJECT = "ADC_DEMO"
+VERSION = "001.000.000"
 
--- 一定要添加sys.lua !!!!
-sys = require("sys")
+-- 在日志中打印项目名和项目版本号
+log.info("main", PROJECT, VERSION)
 
--- 添加硬狗防止程序卡死
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
 if wdt then
     wdt.init(9000) -- 初始化watchdog设置为9s
     sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
 end
 
-local testAdc = require "testAdc"
-sys.taskInit(testAdc.dotest)
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+-- 加载ADC测量功能模块
+require "test_adc"
 
 
 -- 用户代码已结束---------------------------------------------

+ 58 - 0
module/Air8000/demo/adc/readme.md

@@ -0,0 +1,58 @@
+## 演示模块概述
+
+1、main.lua:主程序入口;
+
+2、test_adc.lua:ADC测量功能模块;
+
+## 演示功能概述
+
+使用Air8000开发板测试ADC功能。
+
+## 演示硬件环境
+
+1、Air8000开发板一块
+
+2、TYPE-C USB数据线一根
+
+3、杜邦线若干
+
+4、外部供电电源Air9000P
+
+<img title="" src="https://docs.openLuat.com/cdn/image/8000_adc.jpg" alt="8000_adc.jpg" style="zoom:25%;">
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air8000 V2012版本](https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/core)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录V2012-1固件对比验证)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、Luatools烧录内核固件和demo脚本代码
+
+3、烧录成功后,自动开机运行
+
+4、如下是adc通道0设置ADC_RANGE_MIN量程外部供电1.2V,adc通道1设置ADC_RANGE_MAX量程外部供电1.2V,adc通道2设置ADC_RANGE_MAX量程外部供电3.3V,adc通道3设置ADC_RANGE_MIN量程外部供电3.3V的环境下测试的,代码运行结果如下:
+
+这样设置量程和外部供电是为了更直观的观察两种量程下不同供电电压对精准度的影响,可以看到如下测量的数据是符合预期的
+
+对于Air8000:ADC_RANGE_MIN对应量程为0-1.5V,ADC_RANGE_MAX对应量程为0-3.6V。
+
+在外部供电1.2V的情况下,ADC_RANGE_MIN量程获取到的数据更精准;在外部供电3.3V的情况下,ADC_RANGE_MIN量程下会限制在1.5v左右,ADC_RANGE_MAX可以正常测量。
+
+```
+[2025-09-10 16:13:57.926][000000517.170] I/user.adc通道0 处理值: 1194.88 mV (样本数:10)
+
+[2025-09-10 16:13:57.946][000000517.174] I/user.adc通道1 处理值: 1189.00 mV (样本数:10)
+
+[2025-09-10 16:13:57.967][000000517.178] I/user.adc通道2 处理值: 3376.75 mV (样本数:10)
+
+[2025-09-10 16:13:57.992][000000517.182] I/user.adc通道3 处理值: 1565.00 mV (样本数:10)
+
+[2025-09-10 16:13:58.016][000000517.187] I/user.CPU TEMP 温度值: 34.00 ℃(样本数:10)
+
+[2025-09-10 16:13:58.042][000000517.191] I/user.VBAT 处理值: 4414.75 mV (样本数:10)
+
+```

+ 0 - 59
module/Air8000/demo/adc/testAdc.lua

@@ -1,59 +0,0 @@
-
---[[
-
-8. Air8000内部ADC接口为12bits 外部直流分压为0-3.4V
-9. Air8000内部具有2个ADC接口,ADC0 -- AIO3 ADC1 -- AIO4
-10. 特殊通道, CPU内部温度Temp -- adc.CH_CPU 主供电脚电压 VBAT -- adc.CH_VBAT
-11. 设置分压(adc.setRange)要在adc.open之前设置,否则无效!!
-]]
-
-local testAdc = {}
-
--- adc.setRange(adc.ADC_RANGE_1_2) -- 关闭分压
-adc.setRange(adc.ADC_RANGE_MAX) -- 启用分压
-
-local rtos_bsp = rtos.bsp()
-function adc_pin() -- 根据不同开发板,设置ADC编号
-    log.info("main", "define ADC pin in main.lua")
-    return 0,1,255,255, adc.CH_CPU ,adc.CH_VBAT
-end
-local adc_pin_0,adc_pin_1,adc_pin_2,adc_pin_3,adc_pin_temp,adc_pin_vbat=adc_pin()
-
-
-function testAdc.dotest()
-    if adc_pin_0 and adc_pin_0 ~= 255 then adc.open(adc_pin_0) end
-    if adc_pin_1 and adc_pin_1 ~= 255 then adc.open(adc_pin_1) end
-    if adc_pin_2 and adc_pin_2 ~= 255 then adc.open(adc_pin_2) end
-    if adc_pin_3 and adc_pin_3 ~= 255 then adc.open(adc_pin_3) end
-    if adc_pin_temp and adc_pin_temp ~= 255 then adc.open(adc_pin_temp) end
-    if adc_pin_vbat and adc_pin_vbat ~= 255 then adc.open(adc_pin_vbat) end
-
-    -- 下面是循环打印, 接地不打印0也是正常现象
-    -- ADC的精度都不会太高, 若需要高精度ADC, 建议额外添加adc芯片
-    while true do
-        if adc_pin_0 and adc_pin_0 ~= 255 then --adc0
-            log.debug("adc", "adc" .. tostring(adc_pin_0), adc.read(adc_pin_0)) -- 若adc.get报nil, 改成adc.read
-        end
-        if adc_pin_1 and adc_pin_1 ~= 255 then --adc1
-            log.debug("adc", "adc" .. tostring(adc_pin_1), adc.get(adc_pin_1))
-        end
-        if adc_pin_temp and adc_pin_temp ~= 255 then
-            log.debug("adc", "CPU TEMP", adc.get(adc_pin_temp))
-        end
-        if adc_pin_vbat and adc_pin_vbat ~= 255 then
-            log.debug("adc", "VBAT", adc.get(adc_pin_vbat))
-        end
-        sys.wait(1000)
-    end
-
-    -- 若不再读取, 可关掉adc, 降低功耗, 非必须
-    if adc_pin_0 and adc_pin_0 ~= 255 then adc.close(adc_pin_0) end
-    if adc_pin_1 and adc_pin_1 ~= 255 then adc.close(adc_pin_1) end
-    if adc_pin_2 and adc_pin_2 ~= 255 then adc.close(adc_pin_2) end
-    if adc_pin_3 and adc_pin_3 ~= 255 then adc.close(adc_pin_3) end
-    if adc_pin_temp and adc_pin_temp ~= 255 then adc.close(adc_pin_temp) end
-    if adc_pin_vbat and adc_pin_vbat ~= 255 then adc.close(adc_pin_vbat) end
-
-end
-
-return testAdc

+ 140 - 0
module/Air8000/demo/adc/test_adc.lua

@@ -0,0 +1,140 @@
+--[[
+@module  test_adc
+@summary ADC功能测试
+@version 1.0
+@date    2025.07.15
+@author  王城钧
+@usage
+本功能模块演示的内容为:
+1. ADC通道配置与量程设置
+2. 数据采集并处理
+3. 循环打印处理过的ADC数据
+
+本文件没有对外接口,直接在main.lua中require "test_adc"就可以加载运行;
+]]
+
+--[[
+
+1. Air8000内部ADC接口为12bits,ADC量程为0-3.6V
+2. Air8000内部具有4路通用ADC通道,通道0 -- 3
+3. 特殊通道,CPU内部温度Temp -- adc.CH_CPU,主供电脚电压 VBAT -- adc.CH_VBAT
+4. 设置分压(adc.setRange)要在adc.open之前设置,否则无效!!
+]]
+
+
+local function process_channel(channel_samples, tag)
+    if #channel_samples > 2 then
+        -- 升序排序
+        table.sort(channel_samples)
+        
+        -- 创建剔除极值后的新数组
+        local trimmed = {}
+        for i = 2, #channel_samples-1 do
+            table.insert(trimmed, channel_samples[i])
+        end
+        
+        -- 计算平均值
+        local sum = 0
+        for _, v in ipairs(trimmed) do
+            sum = sum + v
+        end
+        local avg_value = sum / #trimmed
+
+        -- 根据tag进行不同处理  
+        if tag == "CPU TEMP" then  
+            log.info(tag, string.format("温度值: %.2f ℃(样本数:%d)", avg_value/1000, #trimmed+2))  
+        else  
+            log.info(tag, string.format("处理值: %.2f mV (样本数:%d)", avg_value, #trimmed+2)) 
+        end  
+        
+        -- -- 格式化输出
+        -- log.info(tag, string.format("处理值: %.2f mV (样本数:%d)", avg_value, #trimmed+2))
+    else
+        log.info(tag, "样本不足无法处理")
+    end
+end
+
+-- 主采集函数
+function adc_all_func()
+    local num_samples = 10  -- 每个通道采集样本数(可配置)
+    local samples = {
+        [0] = {},  -- 通道0样本数组
+        [1] = {},  -- 通道1
+        [2] = {},  -- 通道2
+        [3] = {},  -- 通道3
+        [4] = {},  -- CH_CPU
+        [5] = {}   -- CH_VBAT
+    }
+    
+    while true do
+        sys.wait(1000)  -- 延时1秒,为了方便观察luatools日志,非必须
+        
+        -- 通道0采集处理
+        adc.setRange(adc.ADC_RANGE_MIN)  
+        -- 设置ADC量程,注意量程设置一定要在adc.open()之前,通道0的量程设置为了adc.ADC_RANGE_MIN
+        -- 此演示对通道0外加了1.2V电压,这样设置与通道1形成对比,方便观察1.2V外部供电下adc.ADC_RANGE_MAX和adc.ADC_RANGE_MIN两种量程的测量精准度。
+        adc.open(0)
+        for _ = 1, num_samples do
+            table.insert(samples[0], adc.get(0))
+        end
+        adc.close(0)
+        process_channel(samples[0], "adc通道0")
+
+        -- 通道1采集处理
+        adc.setRange(adc.ADC_RANGE_MAX) 
+        -- 设置ADC量程,注意量程设置一定要在adc.open()之前,通道1的量程设置为了adc.ADC_RANGE_MAX
+        -- 此演示对通道1外加了1.2V电压,这样设置与通道0形成对比,方便观察1.2V外部供电下adc.ADC_RANGE_MAX和adc.ADC_RANGE_MIN两种量程的测量精准度。
+        adc.open(1)
+        for _ = 1, num_samples do
+            table.insert(samples[1], adc.get(1))
+        end
+        adc.close(1)
+        process_channel(samples[1], "adc通道1")
+        
+        -- 通道2采集处理
+        adc.setRange(adc.ADC_RANGE_MAX) 
+        -- 设置ADC量程,注意量程设置一定要在adc.open()之前,通道2的量程设置为了adc.ADC_RANGE_MAX
+        -- 此演示对通道2外加3.3V电压,这样设置可以与通道3形成对比,方便观察3.3V外部供电下adc.ADC_RANGE_MAX和adc.ADC_RANGE_MIN两种量程的测量精准度。
+        adc.open(2)
+        for _ = 1, num_samples do
+            table.insert(samples[2], adc.get(2))
+        end
+        adc.close(2)
+        process_channel(samples[2], "adc通道2")
+        
+        -- 通道3采集处理
+        adc.setRange(adc.ADC_RANGE_MIN) 
+        -- 设置ADC量程,注意量程设置一定要在adc.open()之前,通道3的量程设置为了adc.ADC_RANGE_MIN
+        -- 此演示对通道3外加3.3V电压,这样设置可以与通道2形成对比,方便观察3.3V外部供电下adc.ADC_RANGE_MAX和adc.ADC_RANGE_MIN两种量程的测量精准度。
+        adc.open(3)
+        for _ = 1, num_samples do
+            table.insert(samples[3], adc.get(3))
+        end
+        adc.close(3)
+        process_channel(samples[3], "adc通道3")
+        
+        -- CPU温度通道采集处理
+        adc.open(adc.CH_CPU)
+        for _ = 1, num_samples do
+            table.insert(samples[4], adc.get(adc.CH_CPU))
+        end
+        adc.close(adc.CH_CPU)
+        process_channel(samples[4], "CPU TEMP")
+        
+        -- VBAT通道采集处理
+        adc.open(adc.CH_VBAT)
+        for _ = 1, num_samples do
+            table.insert(samples[5], adc.get(adc.CH_VBAT))
+        end
+        adc.close(adc.CH_VBAT)
+        process_channel(samples[5], "VBAT")
+        
+        -- 清空样本数组
+        for i = 0, 5 do
+            samples[i] = {}
+        end
+    end
+end
+
+sys.taskInit(adc_all_func)
+