读取模拟电压

读取模拟输入并将电压打印到串行监视器

此示例向您展示如何读取模拟引脚 0 上的模拟输入,将值转换为电压,并将其打印到终端或者VS Code的串行监视器。

硬件要求

  • Arduino板卡
  • 10k欧姆电位器

电路

将电位计的三根线连接到电路板上。 第一个从电位计的一个外部引脚接地。 第二个从电位计的另一个外部引脚电压变为 5 伏。 第三个从电位计的中间引脚连接到模拟输入 0。

通过转动电位计的轴,可以改变连接到电位计中心销的游标两侧的电阻值。 这会改变中心引脚的电压。 当中心与连接5伏的一侧之间的电阻接近于零(而另一侧的电阻接近10k欧)时,中心引脚的电压接近5伏。 当电阻反向时,中心引脚的电压接近 0 伏或接地。 该电压是您作为输入读取的模拟电压。

该板的微控制器内部有一个称为模数转换器或 ADC 的电路,它读取此变化的电压并将其转换为 0 到 1023 之间的数字。当轴沿一个方向转动到底时,有 0 引脚上有 5 伏电压,输入值为 0。当轴沿相反方向旋转到底时,引脚上有 5 伏电压,输入值为 1023。在这期间,analog_read() 返回一个数字 0 到 1023 之间,与施加到引脚的电压量成正比。

电路图

读取模拟电压

代码

创建串口连接

let mut serial = arduino_hal::default_serial!(dp, pins, 57600);

创建ADC连接

let mut adc = arduino_hal::Adc::new(dp.ADC, Default::default());

获取A0引脚并设置为数据输入

let a0 = pins.a0.into_analog_input(&mut adc);

接下来,在代码的主循环中,您需要建立一个变量来存储来自电位计的电阻值(介于 0 到 1023 之间,该变量为u16类型):

let sensor_value = a0.analog_read(&mut adc);

要将值从 0-1023 更改为与引脚正在读取的电压相对应的范围,您需要创建另一个变量(浮点数),并进行一些数学运算。 要缩放 0.0 到 5.0 之间的数字,请将 5.0 除以 1023.0,然后乘以sensor_value:

let voltage = (sensor_value as f32) * 5.0 / 1023.0;

最后,您需要将此信息打印到串行监视器:

ufmt::uwriteln!(&mut serial, "{}",uFmt_f32::Two(voltage)).unwrap_infallible();

注意:此处需要在Cargo.toml中所有profile的配置中加入overflow-check=false。否则,编译链接avr-gcc时会报错。这个问题可以参见github上的这个issue的相关讨论:-Zbuild-std + lto="fat" = undefined reference to core::panicking::panic

编译并运行示例

cargo build
cargo run

完整代码如下:

src/main.rs

/*!
 * Read readouts of A0 ADC channels and convert it to voltage.
 *
 * This example shows you how to read an analog input on analog pin 0, 
 * convert the values from analogRead() into voltage, and print it out to the serial monitor.
 */
#![no_std]
#![no_main]

use arduino_hal::prelude::*;
use panic_halt as _;
use ufmt_float::uFmt_f32;

#[arduino_hal::entry]
fn main() -> ! {
    let dp = arduino_hal::Peripherals::take().unwrap();
    let pins = arduino_hal::pins!(dp);
    let mut serial = arduino_hal::default_serial!(dp, pins, 57600);

    let mut adc = arduino_hal::Adc::new(dp.ADC, Default::default());

    let a0 = pins.a0.into_analog_input(&mut adc);

    loop {
        let sensor_value = a0.analog_read(&mut adc);

        let voltage = (sensor_value as f32) * 5.0 / 1023.0;

        ufmt::uwriteln!(&mut serial, "{}",uFmt_f32::Two(voltage)).unwrap_infallible();

        arduino_hal::delay_ms(1000);
    }
}