无垠的广袤 发表于 2025-6-1 06:26

【AT-START-M412测评】ADC 电压采集与应用——水位监测计

# 【AT-START-M412测评】ADC 电压采集与应用——水位监测计

本文介绍了雅特力 AT32M412 开发板实现 ADC 采集芯片内部电压和 A0 引脚电压并串口打印,进一步结合水位传感器实现水位监测计的应用项目设计。

## 项目介绍

- 芯片内部电压的 ADC 采集;
- A0 引脚通道与外部电压的 ADC 采集;
- ADC 电压采集结合水位传感器的应用——水位监测计项目 .

## 采集内部电压

在之前实现 ADC 采集芯片内部温度的项目基础上,实现 ADC 采集芯片内部电压并串口打印的项目设计。

### 工程创建

- 打开 AT32 Work Bench 软件,选择工作空间,选择目标芯片 `AT32M412CBT7` ,点击 `新建` ;
- 进入 `外设` - `ADC` 选项进行参数配置;
- 使能内部参考电压通道(IN17);
- 开启 ADC 普通组设置,采样时间选择 239.5 个 ADCCLK 周期;

!(data/attachment/forum/202506/01/062150nx9f13fp1obrzf31.jpg "adc_voltage_bench_config.jpg")


- 使能 USART1 选项,选择 `异步模式` ,配置 PA9 和 PA10 引脚为 USART1 模式;
- 进入 SYSTEM 模块,选择 USART1 串口打印;
- 其他参数均为默认,点击 `生成代码` 并打开项目。

### 代码

打开工程后,进入 `user` 目录并打开 `main.c` 文件,添加关键代码

```c++
#include "at32m412_416_wk_config.h"
#include "wk_adc.h"
#include "wk_usart.h"
#include "wk_system.h"

#define ADC_VREF            (3.3)

/* add user code begin 0 */
uint16_t ADC_Read(uint8_t channel)
{
    adc_ordinary_software_trigger_enable(ADC1, TRUE);
    while(adc_flag_get(ADC1, ADC_OCCE_FLAG) == RESET);
    adc_flag_clear(ADC1, ADC_OCCE_FLAG);
    return adc_ordinary_conversion_data_get(ADC1);
}
/* add user code end 0 */

int main(void)
{
wk_system_clock_config();
wk_periph_clock_config();
wk_nvic_config();
wk_timebase_init();
wk_usart1_init();
wk_adc_common_init();
wk_adc1_init();

while(1)
{
    /* add user code begin 3 */
                uint16_t adc_value = ADC_Read(ADC_CHANNEL_17);
                printf("adc_value = %d, internal_voltage = %f V\r\n",adc_value,(double)adc_value*ADC_VREF/4095);
            wk_delay_ms(1000);
    /* add user code end 3 */
}
}
```

保存代码,重新构建工程,上传固件至板端,复位运行。

### 效果

内部电压(通道 17)打印

!(data/attachment/forum/202506/01/062208dk757o8b187xzfku.gif "adc_voltage_print.gif")


## 采集外部电压

在实现 ADC 采集芯片内部参考电压的基础上,实现 ADC 采集外部 I/O 电压并串口打印的项目设计。

### 工程创建

- 打开 AT32 Work Bench 软件,选择工作空间,选择目标芯片 `AT32M412CBT7` ,点击 `新建` ;
- 进入 `外设` - `ADC` 选项进行参数配置;
- 使能 IN0 通道,开启 ADC 普通组设置,采样时间选择 239.5 个 ADCCLK 周期;
- 使能 USART1 选项,选择 `异步模式` ,配置 PA9 和 PA10 引脚为 USART1 模式;
- 进入 SYSTEM 模块,选择 USART1 串口打印;
- 其他参数均为默认,点击 `生成代码` 并打开项目。

### 代码

打开工程后,进入 `user` 目录并打开 `main.c` 文件,添加关键代码

```c++
#include "at32m412_416_wk_config.h"
#include "wk_adc.h"
#include "wk_usart.h"
#include "wk_system.h"

#define ADC_VREF            (3.3)

/* add user code begin 0 */
uint16_t ADC_Read(uint8_t channel)
{
    adc_ordinary_software_trigger_enable(ADC1, TRUE);
    while(adc_flag_get(ADC1, ADC_OCCE_FLAG) == RESET);
    adc_flag_clear(ADC1, ADC_OCCE_FLAG);
    return adc_ordinary_conversion_data_get(ADC1);
}
/* add user code end 0 */

int main(void)
{
wk_system_clock_config();
wk_periph_clock_config();
wk_nvic_config();
wk_timebase_init();
wk_usart1_init();
wk_adc_common_init();
wk_adc1_init();

while(1)
{
    /* add user code begin 3 */
                uint16_t adc_value = ADC_Read(ADC_CHANNEL_0);
                printf("adc_value = %d, A0_voltage = %f V\r\n",adc_value,(double)adc_value*ADC_VREF/4095);
            wk_delay_ms(1000);
    /* add user code end 3 */
}
}
```

保存代码,重新构建工程,上传固件至板端,复位运行。

### 效果

采集 A0 通道的电压并打印

分别接 3.3V 和 GND,精确输出对应的电压值

!(data/attachment/forum/202506/01/062230bppqfcqwrpcxdc9l.gif "adc_A0_voltage_print.gif")


## 应用:水位监测计

根据水位传感器的原理,结合 ADC 外部电压信号采集,设计了水位监测计的项目方案。

### 原理

水位传感器(Water Sensor)可以检测水位高度(检测高度:0 - 40 mm),亦可用作雨滴传感器,用于各种天气状况的监测,检测是否下雨及雨量的大小,广泛应用于汽车自动刮水系统、智能灯光系统和智能天窗系统等。

#### 模块简介

- 当模块上电,电源指示 LED 点亮;
- 工作电压:DC `3.3V - 5V` ;
- 输出类型:模拟信号;

!(data/attachment/forum/202506/01/062318hd2cdvsxpfccfpv2.jpg "water_level_sensor.jpg")


传感器具有 10 条裸露的铜线,其中 5 条是电源铜线,另外 5 条是感测铜线。

走线隔行平行排列,每两条电源铜线间有一条感测铜线。

#### 模块原理图

!(data/attachment/forum/202506/01/062339odui6qrrislisiih.jpg "SCH_water-sensor2.jpg")


参考:水位检测报警 - Telesky .

#### 引脚定义

- S(信号)为模拟输出;
- +(VCC)为传感器供电;
- –(GND)为接地。

!(data/attachment/forum/202506/01/062357fnt94zmdaednaemx.jpg "water_sensor_pinout.jpg")


参考:Arduino Uno 水位传感器 .

#### 运行原理

当平行铜线之间有水时,水浸没的高度不同,电流不同。 铜线间的电阻根据水位的变化而变化。

电阻与水的高度成反比(传感器浸水越深,导电性越好,电阻越小,电流越大)。

!(data/attachment/forum/202506/01/062419qr694gg4gpx9gxww.gif "water_level_sensor_resistance.gif")


参考:水位传感器如何工作并与Arduino接口 .

因此根据 ADC 测量传感器输出的电压,便可以确定水位。

### 硬件连接

| 水位传感器   | AT32M412 |
| ------------ | -------- |
| Signal (S)   | A0       |
| Positive (+) | 3V3      |
| Negative (-) | GND      |

### 水位校准

由于各地的水质差异,导电性能不同,因此需要根据实际情况进行校准。

- 多次校准,取平均值;
- 每次校正前,需将 PCB 表面的平行铜线擦干,待测得电压为 0 时再置入水中,记录水位值和电压值。

#### 校准数据采集

水位 15 毫米,相应的串口输出电压为 0.82 伏特

!(data/attachment/forum/202506/01/062442ellrnkx9w8r88igz.jpg "water_level_measure.jpg")


增加水位高度,采集多组电压-水位数据。

假设 ADC 读取电压(V)与水位高度(mm)为线性相关关系,对上述数据进行拟合

!(data/attachment/forum/202506/01/062500ya6alllv4iaglavj.jpg "excel_fit.jpg")


获得拟合表达式 `y = 27.402 x - 2.4795` .

### 流程图

ADC 采集外部电压并转换为水位高度实现串口打印的工程代码流程图如下

!(data/attachment/forum/202506/01/062517zy0qsg00y7shh0gz.jpg "flowchart_adc_water-level.jpg")


### 工程代码

由于水位高度与传感器模拟信号的电压直接相关,因此可在 A0 采集电压的代码基础上,增加水位高度转换即可。

```c++
while(1)
{
        uint16_t adc_value = ADC_Read(ADC_CHANNEL_0);
        double voltage = (double)adc_value*ADC_VREF/4095;
        double wl = 27.402 * voltage - 2.4795;
        printf("adc_value = %d, A0_voltage = %.2f V, Water_level = %.2f mm\r\n",adc_value,voltage,wl);
    wk_delay_ms(1000);
}
```

保存代码,重新构建工程,上传固件至板端,复位运行。

### 效果

移动水位传感器,模拟水位高度的相对变化

!(data/attachment/forum/202506/01/062541f6155fh8j4eub5uu.gif "water-level-sensor.gif")


**串口打印**

ADC 采集的电压随水位高度发生变化,相应的水位高度值也随之变化

!(data/attachment/forum/202506/01/062557upzpn1pp5oeqp7ph.gif "adc_voltage_water-level.gif")


## 总结

本文介绍了雅特力 AT32M412 开发板实现 ADC 采集芯片内部电压和 A0 引脚电压并串口打印,进一步结合水位传感器实现水位监测计的应用项目设计,为 AT32M412 系列单片机的应用和快速开发提供了参考。

caigang13 发表于 2025-6-2 10:35

这种检测原理的实际应用价值不高

无垠的广袤 发表于 2025-6-2 20:19

caigang13 发表于 2025-6-2 10:35
这种检测原理的实际应用价值不高

实际应用需要根据应用场景选择合适的液位传感器。
这种导电式或电阻式的液位传感器原理也基本上都和介电常数的差异有关;
其他的比如电容式液位传感器、超声波或雷达传感器,也都有各自的适用场景和适用范围。
页: [1]
查看完整版本: 【AT-START-M412测评】ADC 电压采集与应用——水位监测计