analogRead()
针对的是 A0、A1……接口。
在 UNO 板子上:
A0-A5 在板子上有,且印着“IN”,也就是说它只接受输入,用不着设置 pinMode。
A6-A11 则是:4、6、8、9、10、12。
有些仿 UNO 外形,但用 ESP8266 芯片的板子,其只有一个 A0,其他是空的。
int v = analogRead(A0);
读取 A0 接口的模拟输入,其值为 0-1023。
为什么是 0-1023,默认情况下,这个公式是:
(输入电压 - 板子内部电压参考值) / 1023。
UNO 板子,板子内部电压参考值是 5V。
如果我们通过电源接口输入电源(不通过 USB,注意:通过电源接口会损耗更多电,所以需要更高电压),没带负载的情况下,经测试:
当输入电压 > 6.5V,这个电压参考值才是 5V。
当输入电压降低时,这个电压参考值会逐步降低。
有什么影响呢?假如 A0 口接到板子上的 5V 接口。
假如外部电压为 10V,此时 A0 值是 1023,因为 5/5 * 1023。
假如外部电压为 5V,此时 A0 值还是 1023,因为 3.3/3.3 * 1023。(因为经测试外部电压为 5V 时,只能输出约 3.3V。
如果外部电压再低一点,此时 A0 值还是 1023,因为分子、分母都在降低。
而如果再再低,可能是无法驱动主板了。
注意
在 UNO 板子上,读取一次耗时 100 微秒,也就是说 0.1 毫秒。
如果引脚悬空,读取出的值并不是 0,而是不稳定的值。
读取某引脚的值后,要略微间隔再读旁边的引脚,因为读取时会产生电噪声,时间间隔太近,会影响读取结果。
如果 analogRead 之前设置了引脚为 OUTPUT,则可能读取失败,此时需要先设置为 INPUT。
读取数据前,通常需要预热,很多传感器前面一段时间(比如 20 秒)数据是不稳定的。
analogReference()
前面讲了,analogRead 的输入电压太低,则会影响“分母”,所以我们要保证电压在指定范围内,经测试,输入电压在指定范围内,“分母”波动值在 0.02V。
如果我们精度要求不高,且输入电压可能会略微压降,我们可以使用:
analogReference(INTERNAL)
此时分母是 1.1V(ATmega168),或者 2.56V(ATmega328P),由于这个电压显著低于板子驱动电压,所以还是能保证的,并不会大范围跳动。
或者,如果我们要求高精度,则可以将高精度电压输入 AREF 引脚(注意不是 IOREF),然后设置:
analogReference(EXTERNAL)
此时“分母”就是我们 AREF 的电压。
注意
AREF 电压不能低于 0V,不能高于 5V。
如果使用 AREF 电压,则在调用 analogRead 之前,一定要 analogReference(EXTERNAL),否则可能会造成 AREF 电压和内部参考电压短接,可能会损坏主板。
analogWrite()
analogWrite 操纵的不是 A0、A1……口,我们看主板也可以看出 A0、A1 口中只是 IN 标识。
那么 analogWrite 是操纵哪些口呢?是数字接口那边带 ~ 的,即 PWM,也就是说它并不是真的模拟值,而是模拟的模拟值,比如要输出 3V,在一个周期内,60% 是高电平,40% 是低电平。5 * 60%,就等于 3V 了。
注意 analogRead 出来是 0-1023,但是 analogWrite 第二个参数值是:0-255。
注意,本文说的都是 UNO 板子,其他型号的板子,有些可以写 A0、A1……