3. 传感器数据采集:流量计、液位传感器、风速风向传感器选型与接口设计
各位同学,咱们接着往下聊。上一章我们把喷洒系统的核心执行器——泵和喷嘴给定了下来。但光有执行器不行,你得知道它干得怎么样,对吧?这就得靠传感器了。
说白了,传感器就是系统的眼睛和耳朵。流量计告诉你喷了多少,液位计告诉你还剩多少,风速风向仪告诉你环境允不允许你喷。这三个传感器选不好,接口设计不合理,整个喷洒系统就是个瞎子。
我个人习惯,在设计传感器采集方案时,会先问自己三个问题:精度够不够?接口稳不稳?成本扛不扛得住? 咱们一个一个来看。
3.1 流量计:你得知道喷了多少
流量计是喷洒系统的核心反馈元件。没有它,你根本不知道泵到底打出去了多少药液。
3.1.1 选型要点
无人机上用的流量计,我见过的主要就两种:
- 霍尔式流量计:便宜、简单、输出脉冲信号。靠叶轮转动切割磁感线产生脉冲,脉冲频率正比于流量。
- 超声波流量计:精度高、无机械磨损,但贵,而且对安装位置有要求。
我个人更倾向于霍尔式。为什么?因为无人机上空间有限,成本敏感,而且霍尔式的精度对于农业喷洒来说完全够用了。我在项目中遇到过用超声波流量计的情况,结果因为管道里有气泡,读数跳得厉害,最后还得加消泡装置,得不偿失。
关键参数:
- 流量范围:0.5~10 L/min(常见农用无人机范围)
- 脉冲当量:450~600 脉冲/升(不同厂家有差异)
- 工作电压:5V DC
- 输出信号:NPN开漏输出,需上拉
3.1.2 接口设计:UART还是GPIO中断?
霍尔流量计输出的是脉冲信号,说白了就是方波。你不需要用UART去读它,直接用MCU的GPIO中断捕获上升沿或下降沿就行了。
嗯,这里要注意:脉冲频率可能高达几百赫兹,所以中断服务函数要写得尽量短,别在里面做浮点运算。我一般只做计数,然后定时器定时去算频率。
// 伪代码示例:流量计脉冲计数
volatile uint32_t pulse_count = 0;
void EXTI_IRQHandler(void) {
if (EXTI_GetITStatus(FLOW_SENSOR_PIN) != RESET) {
pulse_count++;
EXTI_ClearITPendingBit(FLOW_SENSOR_PIN);
}
}
// 每100ms计算一次流量
void calculate_flow_rate(void) {
static uint32_t last_count = 0;
uint32_t current_count = pulse_count;
uint32_t delta = current_count - last_count;
// 假设脉冲当量为500脉冲/升
float flow_rate = (float)delta / 500.0f / 0.1f; // L/min
last_count = current_count;
}
避坑指南: 我曾经遇到过流量计信号抖动的问题,脉冲边沿有毛刺,导致计数不准。后来在GPIO引脚上加了一个100nF的电容做硬件滤波,同时在软件里做了20ms的去抖延时,问题就解决了。
3.2 液位传感器:别喷到一半没药了
液位传感器看似简单,但坑不少。你想想看,无人机在空中晃动、倾斜,液面本身就不平,怎么测准?
3.2.1 选型对比
| 类型 | 原理 | 接口 | 优点 | 缺点 |
|---|---|---|---|---|
| 电容式 | 利用液体介电常数变化 | I2C/模拟量 | 无机械部件,耐腐蚀 | 受温度影响大 |
| 超声波式 | 发射超声波,测回波时间 | UART/I2C | 非接触,精度高 | 有盲区,受泡沫影响 |
| 浮球式 | 机械浮球带动电位器 | 模拟量 | 简单便宜 | 易卡死,精度低 |
| 压力式 | 测底部液体压力 | 模拟量/I2C | 不受晃动影响 | 需校准大气压 |
我个人比较推荐压力式液位传感器。为什么?因为无人机在飞行中姿态变化大,浮球和电容式都会受晃动影响,而压力式只跟液柱高度有关,跟姿态无关。当然,前提是你要做大气压补偿。
3.2.2 接口设计:I2C还是模拟量?
压力式液位传感器通常有两种输出:模拟电压(0~5V)或数字I2C。
我建议用I2C接口。原因很简单:模拟量需要ADC采样,而ADC会引入噪声,还需要额外的参考电压。I2C直接输出数字量,精度有保障。
但I2C也有坑:线长不能超过30cm,否则信号会衰减。无人机上传感器到飞控板的距离一般也就十几厘米,问题不大。
// I2C读取液位传感器示例(伪代码)
uint8_t read_liquid_level(float *level_cm) {
uint8_t buf[2];
// 传感器地址假设为0x28
if (HAL_I2C_Master_Receive(&hi2c1, 0x28 << 1, buf, 2, 100) != HAL_OK) {
return 0; // 读取失败
}
uint16_t raw = (buf[0] << 8) | buf[1];
// 假设量程0~100cm,对应输出0~4095
*level_cm = (float)raw / 4095.0f * 100.0f;
return 1;
}
注意: 液位传感器安装时,底部要低于药箱最低液面,否则测不到底。我见过有人把传感器装在药箱侧面,结果药液剩1/3时就测不到了,因为传感器位置太高。
3.3 风速风向传感器:能不能喷,它说了算
风速风向传感器,说白了就是判断今天适不适合打药。风速太大,药液会被吹跑,造成漂移,不仅浪费,还可能污染隔壁农田。
3.3.1 选型思路
无人机上用的风速风向传感器,我主要看两种:
- 超声波风速风向仪:无机械部件,精度高,响应快。但贵,一个要上千块。
- 机械式风速仪(风杯+风向标):便宜,但体积大,有磨损,响应慢。
说实话,对于农业无人机来说,超声波式是唯一靠谱的选择。机械式在无人机上根本没法用——你想想看,无人机自己就在飞,产生气流,风杯转得飞快,根本分不清是自然风还是旋翼风。
3.3.2 接口设计:SPI还是UART?
超声波风速风向仪通常支持两种接口:UART(RS232/RS485)或SPI。
我个人习惯用UART。为什么?因为SPI需要4根线,而且主从设备距离不能太远。UART只需要TX/RX两根线,而且很多超声波传感器直接输出NMEA格式的字符串,解析起来很方便。
嗯,这里要提一句:UART的波特率别设太高,9600或19200就够了。风速数据更新频率一般也就1~10Hz,没必要用115200。
// UART接收风速数据解析示例
// 假设传感器输出格式: $WIMWV,风速,单位,风向,单位,A*校验和
void parse_wind_data(char *buffer) {
char *token;
float wind_speed;
float wind_direction;
// 查找$WIMWV
if (strstr(buffer, "$WIMWV") == NULL) return;
// 解析风速
token = strtok(buffer, ",");
token = strtok(NULL, ","); // 跳过$WIMWV
wind_speed = atof(token);
token = strtok(NULL, ","); // 跳过单位
token = strtok(NULL, ","); // 风向
wind_direction = atof(token);
// 更新全局变量
g_wind_speed = wind_speed;
g_wind_direction = wind_direction;
}
避坑指南: 我曾经遇到过风速数据偶尔丢失的问题,后来发现是UART接收缓冲区溢出。解决方案很简单:把接收缓冲区从64字节改成256字节,同时用DMA接收,不用中断逐字节收。
3.4 三种传感器接口对比总结
| 传感器 | 推荐接口 | 线数 | 采样频率 | 注意事项 |
|---|---|---|---|---|
| 霍尔流量计 | GPIO中断 | 1根信号线 | 连续计数 | 需硬件滤波+软件去抖 |
| 压力式液位 | I2C | 2根(SDA+SCL) | 10~50Hz | 线长不超过30cm |
| 超声波风速风向 | UART | 2根(TX+RX) | 1~10Hz | 用DMA接收,防溢出 |
最后说一句:传感器数据采集不是焊上去就能用的。你得考虑电源纹波、信号完整性、软件滤波、异常处理。我每次做新板子,都会先拿示波器看传感器的输出波形,确认没问题了再写驱动代码。这个习惯,建议你们也养成。