基于单片机的水塔水位控制 设计功能: 1、模拟水塔水位监测及控制系统设计; 2、系统可实现通过一个四相步进电机来实现低水位自动加水和高水位自动停止 ; 3、可实现通过超声波传感器SRF04测量水位变化,低水位报警。 4、可实现通过串口来实现主电脑的实时监测。 5、可实现通过液晶屏幕LCD16824来显示水位的高度,相应水位指示灯亮。 《本产品含全套资料包括 程序 仿真 原理图 参考文档.》
先说说硬件配置。整个系统的眼睛是超声波传感器SRF04,这哥们儿装在塔顶朝下发射声波。水位变化1cm,回波时间差就跟着变,测距精度能到3mm左右。接线简单粗暴,Trig接P2.0,Echo接P2.1,供电直接5V怼上。
看这段测距代码:
sbit Trig = P2^0; sbit Echo = P2^1; float get_distance() { Trig = 1; delay_us(12); Trig = 0; while(!Echo); // 等Echo变高 TH1 = TL1 = 0; // 定时器1清零 TR1 = 1; // 启动定时 while(Echo); // 等Echo变低 TR1 = 0; return (TH1*256 + TL1)*0.017; // 计算厘米数 }这里用了定时器捕获回波时间,0.017这个系数是声速折算的。注意超声波模块需要至少60ms的测量周期,别手贱连续触发。
水位数据到手后得让执行机构动起来。四相步进电机用ULN2003驱动,典型的28BYJ-48型号。当水位低于30cm时电机正转抽水,高于80cm时停转。驱动代码的关键在相位切换顺序:
#define MOTOR_PORT P1 unsigned char phase[] = {0x09,0x0c,0x06,0x03}; // 四相八拍 void motor_run(uint8_t dir) { static uint8_t step = 0; if(dir) step = (step+1)%4; // 正转 else step = (step-1)%4; // 反转 MOTOR_PORT = phase[step]; delay_ms(2); // 控制转速 }重点是这个相位表,直接决定了旋转方向。实测发现2ms的步进延时比较合适,再快容易丢步。记得电机电源要和单片机隔离,否则干扰分分钟教你做人。
显示部分用LCD1602有点寒碜,上LCD12864才能显示水位曲线。初始化时记得调对比度电压,不然白屏能亮瞎眼。关键显示函数这样写:
void lcd_show(float level) { unsigned char buf[16]; sprintf(buf, "Level:%.1fcm", level); lcd_write_string(0x80, buf); // 首行显示 // 画水位柱状图 uint8_t blocks = (uint8_t)(level/100.0*16); for(uint8_t i=0; i<blocks; i++) lcd_write_char(0xC0+i, 0xFF); // 底部显示方块 }这里用字符方块拼成柱状图比直接画线更省事,注意屏幕每行只有8个自定义字符位置,别超了。
基于单片机的水塔水位控制 设计功能: 1、模拟水塔水位监测及控制系统设计; 2、系统可实现通过一个四相步进电机来实现低水位自动加水和高水位自动停止 ; 3、可实现通过超声波传感器SRF04测量水位变化,低水位报警。 4、可实现通过串口来实现主电脑的实时监测。 5、可实现通过液晶屏幕LCD16824来显示水位的高度,相应水位指示灯亮。 《本产品含全套资料包括 程序 仿真 原理图 参考文档.》
串口通信最怕数据乱码,建议用modbus协议格式。每隔500ms发送一帧数据:
void uart_send(float level) { uint8_t buf[8]; buf[0] = 0x01; // 设备地址 *(uint16_t*)&buf[1] = htons((uint16_t)(level*10)); // 水位*10转整型 buf[3] = (level<30 || level>80) ? 0xFF : 0x00; // 报警状态 crc = modbus_crc(buf, 5); // 计算CRC校验 send_bytes(buf, 5); }上位机用Python写个接收程序,matplotlib搞个实时曲线,监控室的老王再也不用爬塔看水位了。
报警功能不能光靠屏幕闪,得整点动静。用PNP三极管驱动蜂鸣器,低电平触发:
sbit BUZZER = P3^4; void alarm_check(float level) { static uint8_t beep_flag = 0; if(level < 30) { BUZZER = ~BUZZER; // 交替翻转 delay_ms(200); beep_flag = 1; } else { if(beep_flag) { BUZZER = 1; // 关闭 beep_flag = 0; } } }这种间隙报警比持续响铃更抓耳,注意延时时间别卡死主循环。
系统整合时最头疼优先级问题。建议把水位检测放在定时中断里,确保采样间隔稳定。主循环里处理显示和通信这些实时性要求低的任务。最后别忘了看门狗,万一程序跑飞了至少能自动复位。
整个项目最精彩的部分是水位预测算法——当检测到水位连续5次下降速率超过2cm/s时,提前启动水泵,这骚操作能减少15%的启停次数。代码实现用了个环形队列存最近5次采样值,算斜率超过阈值就触发预启动。
搞电子的都懂,这种项目永远是调试时间比开发时间长。建议先用Proteus仿真电机驱动逻辑,再用真实硬件调传感器参数。最后提醒:防水措施不到位,代码再好也白搭!