MaixCAM MaixPy ADC 使用介绍

更新历史
日期 版本 作者 更新内容
2024-06-11 1.0.0 iawak9lkm 初版文档

ADC 简介

ADC,即模拟信号数字转换器,将一个输入电压信号转换为一个输出的数字信号。由于数字信号本身不具有实际意义,仅仅表示一个相对大小。故任何一个模数转换器都需要一个参考模拟量作为转换的标准,参考标准一般为最大的可转换信号大小。而输出的数字量则表示输入信号相对于参考信号的大小。

ADC 外设一般有两个主要参数:分辨率和参考电压。

  • 分辨率:ADC 的分辨率以输出二进制(或十进制)数的位数来表示。它说明 A/D 转换器对输入信号的分辨能力。一般来说,n 位输出的 A/D 转换器能区分 2^n 个不同等级的输入模拟电压,能区分输入电压的最小值为满量程输入的 1/(2^n)。在最大输入电压一定时,输出位数愈多,分辨率愈高。
  • 参考电压:ADC 参考电压是在 AD 转换过程中与已知电压进行比较来找到未知电压的值的电压。参考电压可以认为是最高上限电压,当信号电压较低时,可以降低参考电压来提高分辨率。

通过板子的 ADC,可以采集外部的电压,并让板子检验电压是否达标,或是在检测到特定的电压时执行特定的任务(例如 ADC 检测多个按钮)。

MaixPy 中使用 ADC

通过 MaixPy 使用 ADC 很简单:

from maix.peripheral import adc
from maix import time

a = adc.ADC(0, adc.RES_BIT_12)

raw_data = a.read()
print(f"ADC raw data:{raw_data}")

time.sleep_ms(50)

vol = a.read_vol()
print(f"ADC vol:{vol}")

使用 ADC0,从中读取原始的转换数据,或是直接从中读取电压数据。

有关 ADC API 的详细说明请看 ADC API 文档

关于 MaixCAM ADC 外设的一些说明

MaixCAM 引出一个连接 ADC 的 IO,为 GPIO B3,如下图所示:

该 IO 默认为 ADC, 无需额外进行配置。

MaixCAM ADC 外设采样精度为 12bit,也就是说采样输出范围为 0~4095。采样精度为参考电压的 1/4096。

MaixCAM ADC 外设的扫描频率不能高于 320K/s,也就是上述示例中增加延时的原因。

MaixCAM ADC 外设内部参考电压Vref为 1.5V,实际使用时会有些许偏差。因为内部参考电压典型值为 1.5V,所以 Soc 的 ADC 量程为 0~1.5V。该量程的 ADC 应用范围较小,故 MaixCAM 额外为 ADC 外设设计了分压电路来增大 ADC 的应用范围,该分压电路如下图所示。由于电路中电阻阻值存在误差、ADC 外设有阻抗、内部参考电压有些许偏差,该分压电路的参考电压 Vin_max 约为 4.6~5.0V。API 中已经选择一个精度较高的默认值,一般情况下无需传递该参数。

若需要较高的精度,可以通过以下步骤计算出该分压电路的参考电压:

  • 先测得 ADC_PIN 的实际输入电压 Vin。

  • 然后测得 ADC1 处的实际输入电压 Vadc,电阻R10的位置可参考这个 BOM 表。

  • 保持第一步的电压输入,在shell中执行以下命令:

    echo 1 > /sys/class/cvi-saradc/cvi-saradc0/device/cv_saradc
    cat /sys/class/cvi-saradc/cvi-saradc0/device/cv_saradc
    

    此时你将获得 ADC 原始数据 adc_data。

  • 接地电阻为 R10,另一个电阻为 R6, 记录它们的阻值。通常,MaixCAM 的 R6 阻值为 10KΩ(10 000Ω),R10 阻值为 5.1KΩ(5 100Ω)。

  • 将上述参数传递给以下 python 代码,即可得出 ADC_PIN 端的量程 [0, Vin_max] (闭区间)。

    def maixcam_get_vin_max(Vin:float, Vadc:float, adc_data:int, r6:int, r10:int, adc_max:int=4095):
        Vref = (Vadc/adc_data)*(adc_max+1)
        r3 = Vadc*r6/(Vin-Vadc)
        Vin_max = (Vref/r3)*(r6+r3)
        return Vin_max
    
    Vin = 3.3		# step 1
    Vadc = 1.06		# step 2
    adc_data=2700	# step 3
    r6=10000		# step 4
    r10=5100		# step 4
    
    if __name__ == '__main__':
        print(maixcam_get_vin_max(Vin, Vadc, adc_data, r6, r10))
    

    现在将结果传递给 adc.ADC() 的第三个参数,你将获得一个高精度的 ADC。