跳转至

adc - 模数转换

作者:王城钧

一、概述

ADC,模拟到数字转换器(Analog-to-Digital Converter),它是一种电子设备或模块,用于将连续变化的模拟信号转换为离散的数字信号,以便数字系统能够对其进行处理和分析。

关于 ADC 的常见指标有两个:

一个是电压输入范围,一个是分辨率;

对某一个确定的模组型号来说,其 ADC 分辨率指标是固定的(目前主流模组都是 12bit),但电压输入范围可能在不同条件上会有所调整,比如 Air780Exx 系列、Air8000 系列等;

特别注意!

合宙主流模组软件上对ADC都可以配置ADC_RANGE_MAX和ADC_RANGE_MIN两种量程
Air8000adc.ADC_RANGE_MIN对应量程为0-1.5V
adc.ADC_RANGE_MAX量程对应0-3.6V

Air780EPM/Air780EHM/Air780EHV/Air780EGHadc.ADC_RANGE_MIN对应量程为0-1.5V
adc.ADC_RANGE_MAX量程对应0-3.6V

Air8101adc.ADC_RANGE_MIN对应量程为0-1.5V
adc.ADC_RANGE_MAX量程对应0-2.4V

1.当被测电压最大值在1.5V以内,使用adc.ADC_RANGE_MIN
2.当被测电压大于1.5V小于3.6V8101小于2.4V),使用adc.ADC_RANGE_MAX,且不添加外部分压电路;
3.当被测量电压最高值在3.6v以上81012.4V以上)时, 使用ADC_RANGE_MIN,且必须添加外部分压电路;

二、核心示例

1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;

2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;

3、更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/adc

**local function adc_all_task**()
    **while** 1 **do**
        sys.wait(1000)--延时1S           
        adc.setRange(adc.ADC_RANGE_MIN)--设置ADC引脚的测量范围0-1.5V,这种方式被测电压可以经过外部电阻分压后再挂在ADC上;
        adc.open(0)--打开ADC通道0
        **local** data0 = adc.get(0)--获取adc计算值,将获取到的值赋给data0
        adc.close(0)--关闭ADC通道0
        log.info("adc通道0", data0)--打印adc计算值

        adc.open(1)--打开ADC通道1
        **local** data1 = adc.get(1)--获取adc计算值,将获取到的值赋给data1
        adc.close(1)--关闭ADC通道1
        log.info("adc通道1", data1)--打印adc计算值

        adc.open(2)--打开ADC通道2
        **local** data2 = adc.get(2)--获取adc计算值,将获取到的值赋给data2
        adc.close(2)--关闭ADC通道2
        log.info("adc通道2", data2)--打印adc计算值

        adc.open(3)--打开ADC通道3
        **local** data3 = adc.get(3)--获取adc计算值,将获取到的值赋给data3
        adc.close(3)--关闭ADC通道3
        log.info("adc通道3", data3)--打印adc计算值

        adc.open(adc.CH_CPU)--打开adc.CH_CPU通道
        **local** data5 = adc.get(adc.CH_CPU)--获取adc.CH_CPU计算值,将获取到的值赋给data5
        adc.close(adc.CH_CPU)--关闭adc.CH_CPU通道
        log.info("CPU TEMP", data5)--打印adc.CH_CPU计算值

        adc.open(adc.CH_VBAT)--打开adc.CH_VBAT通道
        **local** data6 = adc.get(adc.CH_VBAT)--获取adc.CH_VBAT计算值,将获取到的值赋给data6
        adc.close(adc.CH_VBAT)--关闭adc.CH_VBAT通道
        log.info("VBAT", data6)--打印adc.CH_VBAT计算值
    **end**  
**end**

sys.taskInit(**adc_all_task**)

三、常量详解

核心库常量,顾名思义是由合宙 LuatOS 内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;

合宙模组的 adc 量程一些说明:

合宙主流模组软件上对ADC都可以配置ADC_RANGE_MAX和ADC_RANGE_MIN两种量程
Air8000adc.ADC_RANGE_MIN对应量程为0-1.5V
adc.ADC_RANGE_MAX量程对应0-3.6V

Air780EPM/Air780EHM/Air780EHV/Air780EGHadc.ADC_RANGE_MIN对应量程为0-1.5V
adc.ADC_RANGE_MAX量程对应0-3.6V

Air8101adc.ADC_RANGE_MIN对应量程为0-1.5V
adc.ADC_RANGE_MAX量程对应1.5-2.4V

1.当被测电压最大值在1.5V以内,使用adc.ADC_RANGE_MIN
2.当被测电压大于1.5V小于3.6V8101小于2.4V),使用adc.ADC_RANGE_MAX,且不添加外部分压电路;
3.当被测量电压最高值在3.6v以上81012.4V以上)时, 使用ADC_RANGE_MIN,且必须添加外部分压电路;

合宙模组的 adc id 的一些说明:

Air8000ADC0对应通道ID0ADC1对应通道ID1ADC2对应通道ID2ADC3对应通道ID3

Air780EPM/Air780EHM/Air780EHV/Air780EGHADC0对应通道ID0ADC1对应通道ID1
ADC2对应通道ID2ADC3对应通道ID3

Air8101Air8101 内部具有 6  ADC 接口通道,
ADC1对应通道ID1为例,以此类推。

Air8101有ADC1ADC2ADC3ADC4ADC5ADC6ADC10
ADC12ADC13ADC14,一共10路外部ADC
10ADC复用的对应关系为
ADC1 对应 ADC10
ADC2 对应 ADC12
ADC3 对应 ADC13
ADC4 对应 ADC14
ADC5  ADC6没有对应的其他ADC通道
这里的对应关系如何理解呢?
ADC1 对应 ADC10为例,意思是在Air8101内部ADC1和ADC10是同一个ADC通道
ADC1和ADC10不能同时使用

adc.ADC_RANGE_MAX

常量含义:合宙主流模组ADC引脚的测量范围0-3.6VAir8101的测量范围0-2.4V
         注意!仅适用于无外部分压电路的情况;
数据类型:number
取值范围:14
示例代码:adc.setRange(adc.ADC_RANGE_MAX)

adc.ADC_RANGE_MIN

常量含义:合宙主流模组ADC引脚的测量范围0-1.5V
         注意!适用于两种情况,一种是本身就小于1.5V无需外部分压电路,一种是本身大于1.5V需要外部分压电路
数据类型:number
取值范围:0
示例代码:adc.setRange(adc.ADC_RANGE_MIN)

CH_CPU

常量含义:CPU内部温度的通道id
数据类型:number
取值范围:-1
示例代码:adc.open(adc.CH_CPU)

adc.CH_VBAT

常量含义:VBAT供电电压的通道id
数据类型:number
取值范围:-2
示例代码:adc.open(adc.CH_VBAT)

四、函数详解

adc.open(id)

功能

打开 adc 通道

参数

id

参数含义:通道id,通常从0开始;
数据类型:number
取值范围:参考第三章合宙模组的adc id的一些说明
是否必选:必须传入此参数;
注意事项:暂无;
参数示例:0123adc.CH_CPUadc.CH_VBAT

返回值

local result = adc.open(id)

result

含义说明:表示返回结果,失败返回false,成功返回true
数据类型:boolean
取值范围:true或false
注意事项:暂无;
返回示例:true

示例

-- 打开adc通道4,并读取
if adc.open(3) then
    log.info("adc", adc.read(3)) -- 返回值有2个, 原始值和计算值,通常只需要后者
    log.info("adc", adc.get(3))  -- 返回值有1个, 仅计算值
end
adc.close(3) -- 若需要持续读取, 则不需要close, 功耗会高一点.

adc.setRange(range)

功能

设置 ADC 的测量范围

参数

range

参数含义:表示adc通道的量程的最大值
数据类型:number
取值范围:ADC_RANGE_MIN和ADC_RANGE_MAX,参考第三章合宙模组的adc量程一些说明
是否必选:必须传入此参数;
注意事项:adc.CH_VBAT和adc.CH_CPU不需要设置量程,在模组正常工作时都可以正常测量;
参数示例:adc.ADC_RANGE_MAXadc.ADC_RANGE_MIN

返回值

nil

示例

adc.setRange(adc.ADC_RANGE_MIN)

adc.read(id)

功能

读取 adc 通道的原始值和计算值(启用分压后可超量程测电压,但不建议使用避免烧坏)

参数

id

参数含义:通道id,通常从0开始;
数据类型:number
取值范围:参考第三章合宙模组的adc id的一些说明
是否必选:必须传入此参数;
注意事项:暂无;
参数示例:0123adc.CH_CPUadc.CH_VBAT

返回值

local data0,data1 = adc.read(id)

data0

含义说明:adc原始值
数据类型:number
取值范围:当量程设置为adc.ADC_RANGE_MIN,最大可获取到4096(可超量程测量,但容易损坏ADC芯片)
         当量程设置为adc.ADC_RANGE_MAX,最大可测量到4096(可超量程测量,但容易损坏ADC芯片);
         8101对应6058)(可超量程测量,但容易损坏ADC芯片);
注意事项:暂无;
返回示例:暂无;

data1

含义说明:从原始值换算得出的实际值,单位是mV
数据类型:number
取值范围:当量程设置为adc.ADC_RANGE_MIN,最大可获取到1.5V(可超量程测量,但容易损坏ADC芯片)
         当量程设置为adc.ADC_RANGE_MAX,最大可测量到3.6V8101对应2.4V);
        (可超量程测量,但容易损坏ADC芯片)
注意事项:暂无;
返回示例:暂无;

示例

local function adc_task()
     while 1 do
         sys.wait(1000)--延时1S
         adc.setRange(adc.ADC_RANGE_MIN)--设置ADC引脚的测量范围0-1.5V,这种方式被测电压可以经过外部电阻分压后再挂在ADC上;
         adc.open(0)--打开ADC通道1
         local data0,data1 = adc.read(0)--获取adc的原始值和计算值,将获取到的值赋给data0,data1
         adc.close(0)--关闭ADC通道1
         log.info("adc通道0", data0,data1)--打印adc计算值
     end
 end

sys.taskInit(adc_task)

adc.get(id)

功能

获取 adc 计算值(启用分压后可超量程测电压,但不建议使用避免烧坏)

参数

id

参数含义:通道id,从0开始;
数据类型:number
取值范围:参考第三章合宙模组的adc id的一些说明
是否必选:必须传入此参数;
注意事项:暂无;
参数示例:0123adc.CH_CPUadc.CH_VBAT

返回值

local data = adc.get(id)

data

含义说明:单位是mV,  如果是adc.CH_CPU通道会返回温度值,单位千分之一摄氏度,若读取失败,会返回-1
数据类型:number
取值范围:当量程设置为adc.ADC_RANGE_MIN,最大可获取到1.5V(可超量程测量,但容易损坏ADC芯片)          当量程设置为adc.ADC_RANGE_MAX,最大可测量到3.6V8101对应2.4V          (可超量程测量,但容易损坏ADC芯片);,
         当量程设置为adc.ADC_RANGE_MAX,最大可测量到3.6V8101对应2.4V);
        (可超量程测量,但容易损坏ADC芯片)
         对于温度测量,最大值为66.2摄氏度;
注意事项:启用分压后可超量程测电压,但不建议使用避免烧坏;
返回示例:暂无;

示例

local function adc_task()
     while 1 do
         sys.wait(1000)--延时1S
         adc.setRange(adc.ADC_RANGE_MIN)--设置ADC引脚的测量范围0-1.5V,这种方式被测电压可以经过外部电阻分压后再挂在ADC上;
         adc.open(0)--打开ADC通道1
         local data = adc.get(0)--获取adc计算值,将获取到的值赋给data
         adc.close(0)--关闭ADC通道1
         log.info("adc读出值", data)--打印adc计算值
     end
 end

sys.taskInit(adc_task)

adc.close(id)

功能

关闭 adc 通道

若需要持续读取, 则不需要 close, ADC 工作时的功耗大概是 400uA 左右;

若不需要持续读取,则需要 close,否则 ADC 通道将浪费至少 400uA 左右;

参数

id

参数含义:通道id,从0开始;
数据类型:number
取值范围:参考第三章合宙模组的adc id的一些说明
是否必选:必须传入此参数;
注意事项:暂无;
参数示例:0123adc.CH_CPUadc.CH_VBAT

返回值

nil

示例

adc.close(1)

五、产品支持说明

支持 LuatOS 开发的所有产品都支持 adc 核心库。