设计与准备
开发环境准备
将Arduino核心板用USB线连接至电脑。检查Arduino的USB驱动是否安装成功,成功之后会在windows设备管理器中出现:
从官网下载arduino-1.8.19,解压。
用实例程序BLINK测试上传是否成功、BLINK程序是否正常工作。直到没有问题。
电路设计
在官方Analog Read Serial | Arduino Documentation的电路图:
的基础上,把电位器改成10kΩ电阻,不要VCC红线。从电阻两端引出导线作为探针,去探测被测的电池等的电压。
元件准备
Arduino核心板及USB连接线、面板包、万用表、10kΩ电阻、导线、电烙铁等。
用电烙铁在Arduino核心板A0口、VCC口、GND口焊上导线。
按电路设计连接导线。
实践
源代码
在Arduino IDE中编写源代码,如下:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
float voltage = sensorValue * (5.0 / 1023.0); // 将读数转换为电压值
Serial.print("SrcData=");
Serial.print(sensorValue);
Serial.print(", %VREF=");
Serial.print(sensorValue / 10.230, 1); // 百分比
Serial.print("%, V@5V=");
Serial.print(voltage, 2); // 打印电压值(限制小数点后2位)
Serial.println("V");
delay(500); // delay in between reads for stability
}
试验
测电池电压,探针正极(直连A0口)接电池正极,探针负极(直连GND口)接电池负极。
用万用表测干电池电压1.31V,用上述电路测,在Arduino串口监视器中看到的是1.38V。
用万用表测锂电池电压4.0V,用上述电路测得4.3V:
万用表测VCC和GND之间的电压,是4.66V。于是用4.66*86%,得到4.01V。与万用表所测结果非常相近。
仅接入锂电池正极也能得到电压,但表现怪异,例如结果可能为:
结论
Arduino测得结果比较精准。与万用表基本接近,误差非常小。但前提是换算时要给出正确的参考电压。有VREF输入则用VREF,否则VREF应该是VCC-GND,而不是5V。
更进一步
深入理解analogRead
Arduino 板包含一个多通道、10 位模数转换器。这意味着它将把 0 到工作电压之间的输入电压映射为 0 到 1023 之间的整数值。例如,在 5V Arduino UNO 上,这会产生读数之间的分辨率:5 伏/1024 单位或每单位 0.0049 伏 (4.9 mV)。
输入范围可以使用AnalogReference()更改,而分辨率可以使用AnalogReadResolution()更改(仅适用于 Zero、Due 和 MKR 板) 。
在基于 ATmega 的主板(UNO、Nano、Mini、Mega)上,读取模拟输入大约需要 100 微秒(0.0001 秒),因此最大读取速率约为每秒 10,000 次。
综上,模拟电压读取的两个关键指标:A/D分辨率10bits,电压分辨力几个mV,时间分辨力0.1mS。
尚存疑问:若参考电压AREF设置为1V,电压分辨力是否进一步精确到1mV?若参考电压AREF设置为1mV,电压分辨力是否进一步精确到1μV?
深入理解AnalogReference
analogReference(type)中的type可取值及含义:
-
DEFAULT:默认模拟参考电压为 5 伏(在 5V Arduino 板上)或 3.3 伏(在 3.3V Arduino 板上)
-
INTERNAL:内置参考电压,在 ATmega168 或 ATmega328P 上等于 1.1 伏,在 ATmega32U4 和 ATmega8 上等于 2.56 伏(Arduino Mega 不可用)
-
INTERNAL1V1:内置 1.1V 参考电压(仅限 Arduino Mega)
-
INTERNAL2V56:内置 2.56V 参考电压(仅限 Arduino Mega)
-
外部:施加到 AREF 引脚的电压(仅限 0 至 5V)用作参考。
注意事项和警告
请勿在 AREF 引脚上使用低于 0V 或高于 5V 的外部参考电压!如果您在 AREF 引脚上使用外部参考,则必须在调用analogRead()
之前将模拟参考设置为 EXTERNAL 。否则,内置参考电压源会和AREF引脚短接在一起,可能会损坏 Arduino 板上的微控制器。(这里发出了一个烧毁板子的警告!)
或者,您可以通过 5K 电阻将外部参考电压连接到 AREF 引脚,从而允许您在外部和内部参考电压之间切换。请注意,该电阻器将改变用作参考的电压,因为 AREF 引脚上有一个内部 32K 电阻器。两者充当分压器,因此,例如,通过电阻器施加的 2.5V 将在 AREF 引脚上产生 2.5 * 32 / (32 + 5) = ~2.2V。
更改模拟参考值后,前几个读数analogRead()
可能不准确。
对前面的设计进行改进(待验证)
鉴于默认参考电压(5V)不准确,鉴于AREF接入外部电压源有烧板子的风险,优先考虑修改参考电压analogReference(INTERNAL1V1)和analogReference(INTERNAL2V56)进行尝试,检查这里所谓的1.1V和2.56V是否足够精确。如果不行,可能仍须将AREF接入有精确电压值(例如精确等于1V)的外部电压源才能得到想要的结果。
在WOKWI在线仿真平台上测试,发现 analogReference(INTERNAL);是可以生效的。当A0口提供的电压超过1.1V,结果都是最大值1023。
原理上尚存的疑问(待学习)
内部D/A转换器的原理如何?其对外等效电阻是否为32kΩ?所有外部电源电路负极是否需要与GND口连接?