首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >用安信可WiFi蓝牙模组做一个水位监测器

用安信可WiFi蓝牙模组做一个水位监测器

原创
作者头像
安信可科技
发布2025-05-16 17:35:14
发布2025-05-16 17:35:14
3190
举报
文章被收录于专栏:DIYDIY

本作品由安信可论坛用户无垠的广袤 制作。

水位检测在水资源管理、城市防洪、农业灌溉、家用电器和工业生产等多领域发挥积极建设作用。利用水位传感器,可以实现水资源的智能管理,提高生产效率。

本文介绍了安信可 Ai-M61-32S 开发板结合水位传感器实现水位监测计的项目设计。

项目方案

通过读取 IO 接口的模拟值,进行电压转换,获取检测到的电压值,进一步通过电压-水位校准,实现水位高度的串口打印和串口绘图,实时水位监测功能。

电压转换

根据欧姆定律,V = I / R,电压和电阻成正比;

因此通过获取 3.3V 和 GND 对应的模拟数值(实测为 3199 和 21),

即可得到实际电压的转换公式 Valtage = val * (3.3 / (3199-21)) .

代码

#include <stdio.h> void setup() { pinMode(19, INPUT); Serial.begin(115200); } void loop() { int val = analogRead(19); // analog value reading float vlt = val * (3.3 / (3199-21)); // real voltage conversion Serial.println(vlt); delay(200); }

按住 IO2 键的同时,短按 EN 键,进入下载模式,配置端口号后上传工程,复位运行程序。

效果

水位传感器

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

模块简介

当模块上电,电源指示 LED 点亮;

工作电压:DC 3.3V - 5V ;

输出类型:模拟信号;

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

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

模块原理图

参考:水位检测报警 - Telesk

引脚定义

S(信号)为模拟输出;

+(VCC)为传感器供电;

–(GND)为接地。

参考:Arduino Uno 水位传感器

运行原理

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

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

动图封面
动图封面

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

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

硬件连接

S -> IO19

+ -> 3V3

- -> GND

硬件连接完成后,打开串口,此时输出的电压值应为 0 。

水位校准

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

多次校准,取平均值;

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

校准数据采集

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

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

假设 ADC 读取电压(V)与水位高度(mm)为线性相关关系,对上述数据进行拟合。使用 Excel 软件进行拟合,获得拟合表达式 y = 41.774 x - 38.686。

工程代码

在代码中添加相应的水位高度定义

#include <stdio.h>void setup() { pinMode(19, INPUT); Serial.begin(115200); } void loop() { int val = analogRead(19); // analog sensor value float vlt = val * (3.3 / (3199-21)); // real voltage conversion float wl = 41.774 * vlt - 38.686; // water level (mm) Serial.print(val); Serial.print(","); Serial.print(vlt); Serial.print(","); Serial.println(wl); delay(200); }

保存代码,构建工程,上传固件,复位后运行程序。

打开串口助手,连接目标串口对应的设备端口号,打开串口,获取实时 IO 模拟值、电压值(伏特)和水位值(毫米)。

效果演示

动图封面
动图封面

对应的水位演化曲线

动图封面
动图封面

水位的数码管显示

在前面关于 ADC 读取电压并结合水位传感器实现电压-水位高度转换的基础上,增加 4 位共阳 数码管显示 水位高度的功能。

硬件连接

这里采用 2 个 74HC595 驱动的 4 位共阳数码管,支持 3.3V 至 5V 的宽电压输入,仅需 3 个信号引脚即可驱动。

水位传感器接线方式

Water-sensor_S -> IO19

Water-sensor_+ -> 3V3

Water-sensor_- -> GND

数码管接线方式

4Bit-segment_SCLK -> IO23

4Bit-segment_RCLK -> IO24

4Bit-segment_DIO -> IO11

工程代码

#include <stdio.h> const int sensorPin = 19; // water-level sensor pin // 74HC595 引脚设置 const int latchPin = 24; // RCLK const int clockPin = 23; // SCLK const int dataPin = 11; // DIO unsigned char num[]={0xC0, //"0" 0xF9, //"1" 0xA4, //"2" 0xB0, //"3" 0x99, //"4" 0x92, //"5" 0x82, //"6" 0xF8, //"7" 0x80, //"8" 0x90 //"9" }; void setup() { pinMode(latchPin,OUTPUT); pinMode(clockPin,OUTPUT); pinMode(dataPin,OUTPUT); pinMode(sensorPin, INPUT); // uart setting Serial.begin(115200); } /* ------------ loop for serial print and segment display -------------- */ void loop() { int count = 0; int val = analogRead(sensorPin); // analog sensor value float vlt = val * (3.3 / (3199-21)); // real voltage conversion float wl = 41.774 * vlt - 38.686; // water level (mm) //Serial.print("Analog Value: "); Serial.print(val); // in order to serial plot Serial.print(", "); //Serial.print("Voltage: "); Serial.print(vlt); //Serial.print("V"); Serial.print(", "); //Serial.print("Water Level: "); Serial.println(wl); //Serial.println("mm"); Serial.println((String)"Analog Value: " + val + ", Valtage: " + vlt + "V, Water Level: " + wl + "mm"); // serial print string while (count < 25) // loop 25 times for delay 500ms (20ms every display) { if (wl < 0){ disp(0); }else{ disp(wl); // display water level } count++; } } /* ------------ segment display number (dynamics scanning) -------------- */ void disp(float n) { int t = 5; int yi = ((int)(n*10))%10; int ge = (int)n%10; int shi = ((int)n/10)%10; int bai = ((int)n/100)%10; if(bai>0){ shiftOut(dataPin,clockPin,MSBFIRST,num[bai]); }else{ shiftOut(dataPin,clockPin,MSBFIRST,0xFF); } shiftOut(dataPin,clockPin,MSBFIRST,0b00001000); digitalWrite(latchPin, HIGH); delay(t); digitalWrite(latchPin,LOW); if(shi>0){ shiftOut(dataPin,clockPin,MSBFIRST,num[shi]); }else{ if(bai>0){ shiftOut(dataPin,clockPin,MSBFIRST,num[0]); }else{ shiftOut(dataPin,clockPin,MSBFIRST,0xFF); } } shiftOut(dataPin,clockPin,MSBFIRST,0b00000100); digitalWrite(latchPin, HIGH); delay(t); digitalWrite(latchPin,LOW); shiftOut(dataPin,clockPin,MSBFIRST,num[ge]&0x7F);//与运算加入小数点 shiftOut(dataPin,clockPin,MSBFIRST,0b00000010); digitalWrite(latchPin, HIGH); delay(t); digitalWrite(latchPin,LOW); shiftOut(dataPin,clockPin,MSBFIRST,num[yi]); shiftOut(dataPin,clockPin,MSBFIRST,0b00000001); digitalWrite(latchPin, HIGH); delay(t); digitalWrite(latchPin,LOW); } /* ------------ shiftOut -------------- */ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) { uint8_t i; for (i = 0; i < 8; i++) { if (bitOrder == LSBFIRST) digitalWrite(dataPin, !!(val & (1 << i))); else digitalWrite(dataPin, !!(val & (1 << (7 - i)))); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } }

●注意 shiftOut 函数需要定义;

●由于每次采样数值均存在较大波动,为了避免数码管动态刷新过于频繁,加入循环延长数据刷新时间;

●或者多次采样取平均值,进而减小水位数值的波动,使数码管的显示更稳定。

效果显示

数码管显示水位

动态

动图封面
动图封面

串口输出电压和水位值

动图封面
动图封面

动态水位的演化曲线

动图封面
动图封面

静态水位的演化曲线

动图封面
动图封面

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目方案
  • 电压转换
  • 代码
  • 效果
  • 水位传感器
  • 模块简介
  • 模块原理图
  • 运行原理
  • 硬件连接
  • 水位校准
  • 校准数据采集
  • 工程代码
  • 效果演示
  • 对应的水位演化曲线
  • 水位的数码管显示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档