跳转至

ADC

一、模数转换(ADC)概述

1.1 ADC 简介

ADC 通常指模拟/数字转换器,是指将连续变量的模拟信号转换为离散的数字信号的器件。 合宙 Cat.1 模块 ADC 接口主要用来检测模拟电压信号量,用于电池电压检测,温湿度检测,TDS 检测等应用。
ADC 的核心功能:
将模拟信号(如电压、电流、温度、声音等)转换为数字信号(二进制代码),以便数字系统处理、存储或传输。

1.2 ADC 接口介绍

根据 Air780EHV 产品手册可知:

1. Air780EHV 内部 ADC 接口精度为 12bits。
2. Air780EHV 内部具有 4 个 ADC 接口,ADC0 ~ ADC3。
3. 两个特殊通道 :
- CPU 内部温度 Temp : -- adc.CH_CPU - 主供电脚电压 VBAT : -- adc.CH_VBAT
注意事项: 设置分压(adc.setRange)要在 adc.open 之前设置,否则无效!!

1.3 输入电压的范围

Air780EHV 关闭分压后,量程范围 0~1.1V 注意:外接输入电压切记不可超过量程,否则有烧毁风险!!!

-- 设置ADC引脚的测量范围0-3.6V,这种方式被测电压不可经过外部电阻分压后再挂在ADC上;  
 adc.setRange(adc.ADC_RANGE_MAX) 

 -- 设置ADC引脚的测量范围0-1.1V,这种方式被测电压可以经过外部电阻分压后再挂在ADC上;  
 adc.setRange(adc.ADC_RANGE_MIN)

-- 说明:  
-- 当被测量电压最高值在1.5v以内时, 推荐使用ADC_RANGE_MIN,且不添加外部分压电路;   
-- 当被测量电压最高值在3.6v以内时, 推荐使用ADC_RANGE_MAX,且不添加外部分压电路;  
-- 当被测量电压最高值在3.6v以上时, 推荐使用ADC_RANGE_MIN,且必须添加外部分压电路;

二、演示功能概述

本章节演示了 获取 Air780EHV 内部 2 个 ADC 接口以及 2 个特殊通道的获取 adc 计算值的使用教程。
2 个 ADC 接口:ADC0 和 ADC1
2 个特殊通道:
- CPU 内部温度 Temp -- adc.CH_CPU - 主供电脚电压 VBAT -- adc.CH_VBAT

1. 通过 adc.get()读取 ADC 的外部输入模拟电压,

注:启用分压后可超量程测电压,但不建议使用避免烧坏,若想测量更高的外部电源电压,需要外接分压电阻,本教程外部输入电压在 3.2v 以内,需要外部电源与模组共地,保持参考电压一致

2. 通过 adc.get(adc.CH_VBAT)读取供电电压

3. 通过 adc.get(adc.CH_CPU)读取 CPU 温度

三、准备硬件环境

参考:硬件环境清单第二章节内容,准备以及组装好硬件环境。

3.1 直流稳压电源

合宙功耗分析仪 Air9000P,淘宝购买链接:Air9000P 淘宝购买链接

3.2 Air780EHV 开发板

3.3 开发板组合演示

3.3.1 读取 ADC0

3.3.2 读取 ADC1

四、软件环境

1. Luatools 工具

2. 内核固件文件(底层 core 固件文件):LuatOS-SoC_V2007_Air780EHV;参考项目使用的内核固件(当前版本仅供测试使用);

3. LuatOS 需要的脚本和资源文件
脚本和资源文件点我,查看 demo 链接
lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;
准备好软件环境之后,接下来查看如何烧录项目文件到 Air780EHV 开发板,将本篇文章中演示使用的项目文件烧录到 Air780EHV 开发板中。

五、代码 API 和代码解析

5.1 API 接口介绍

本教程使用 api 接口为:adc - 模数转换 - LuatOS 文档

5.2 代码解析

5.2.1 ADC 引脚定义

  • 返回值:
  • 0, 1:普通 ADC 通道。
  • 255:无效通道(占位符,表示未使用)。
  • adc.CH_CPU:CPU 温度传感器通道。
  • adc.CH_VBAT:供电电压检测通道。
function adc_pin()
    --Air780EHV开发板ADC编号
    -- 默认不开启分压,范围是0-1.1v精度高
    -- 开启分压后,外部输入最大不可超过3.3V
    -- 设置分压要在adc.open之前设置,否则无效!!
    adc.setRange(adc.ADC_RANGE_MAX)
    return 0,1,255,255,adc.CH_CPU ,adc.CH_VBAT
end

5.2.2 初始化 ADC 通道

local adc_pin_0,adc_pin_1,adc_pin_2,adc_pin_3,adc_pin_temp,adc_pin_vbat=adc_pin()

    if adc_pin_0 and adc_pin_0 ~= 255 then adc.open(adc_pin_0) end --开启 ADC0
    if adc_pin_1 and adc_pin_1 ~= 255 then adc.open(adc_pin_1) end--开启ADC1
    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--开启adc.CH_CPU 
    if adc_pin_vbat and adc_pin_vbat ~= 255 then adc.open(adc_pin_vbat) end--开启adc.CH_VBAT

5.2.3 循环读取所有 ADC 通道

while true do
        if adc_pin_0 and adc_pin_0 ~= 255 then
            log.debug("adc", "adc" .. tostring(adc_pin_0), adc.get(adc_pin_0))
        end
        if adc_pin_1 and adc_pin_1 ~= 255 then
            log.debug("adc", "adc" .. tostring(adc_pin_1), adc.get(adc_pin_1))
        end
        if adc_pin_2 and adc_pin_2 ~= 255 then
            log.debug("adc", "adc" .. tostring(adc_pin_2), adc.get(adc_pin_2))
        end
        if adc_pin_3 and adc_pin_3 ~= 255 then
            log.debug("adc", "adc" .. tostring(adc_pin_3), adc.get(adc_pin_3))
        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

5.2.4 关闭 ADC 通道(可选)

-- 若不再读取, 可关掉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

六、运行结果展示

可以将 adc0/adc1 外接稳压电源供电,注意供电不可超过量程!(本示例启用分压后量程 0~3.6V), 本示例将 adc0,adc1 输入 3V(电源正极接 adc1,负极接 GND),查看 Luatools 的 log 如下(返回值单位为 mV):

6.1 adc0 读取情况

6.2 adc1 读取情况

6.3 特殊通道读取情况

七、总结

本教程简单举例了如何读取 adc 输入电压、读取供电电压、读取 CPU 温度,除此之外,adc 可以将各种连续变化的模拟信号(如温度、湿度、压力、电压、电流等)转换为离散的数字信号,本模块内部 ADC 精度 12bits,对许多应用已经足够,如温湿度传感器、压力传感器、音频信号处理等,然而对于需要更高精度的应用,可以外挂更高精度的 ADC,如 16 位,24 位等。使用过程中需注意量程范围,不可超出量程。

八、常见问题

1.为什么 ADC 输入 3V,读取模拟电压只有 1.1V?

未启用分压时,量程最高只能到达 1.1V,若想测量 3V,需启用分压。

2. ADC 测量电压来回跳变,为什么?

看外部输入电压是否与模块共地,正常情况需要共地,保持参考电压一致。

3.adc.read()和 adc.get()要用哪一个?

使用 adc.get(),adc.read()不使用。
adc.get()返回的就是计算值,通常单位是 mV,推荐使用这个接口来获取电压值。