多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

基于STM32的智慧养猪系统:环境监测与远程报警实战解析

基于STM32的智慧养猪系统:环境监测与远程报警实战解析 凌晨1点猪舍温度悄悄跌到15℃风机没开、加热器没动我却被手机上的报警震醒。爬起来远程看了一眼温度曲线正在往下掉。这要搁以前只能靠人去现场摸猪耳朵、看猪鼻子判断冷暖半夜稍不注意就是损失。做这个基于STM32的智慧养猪系统初衷很朴素把温度、湿度、氨气、料位、水位这些原本靠经验、靠人巡视的变量变成一套能自动采集、自动控制、远程报警的闭环系统。这篇内容从硬件选型、电路设计、软件架构到现场安装完整摊开我自己的实操过程。适合已经入门STM32、想独立啃下一个完整项目的朋友也适合拿来做毕业设计或小型智能农业项目参考。1. 项目由来与技术选型1.1 猪舍管理的真实痛点很多人觉得养猪就是把猪喂饱实际上猪比想象中娇气得多。猪的汗腺不发达皮下脂肪厚体温调节能力很差环境温度一旦超过适温区马上就会出现热应激表现就是采食量下降、精神萎靡严重的直接喘气不止。成年猪的适温区大约在16~26℃哺乳仔猪则需要30℃以上的保温区同一个猪舍里不同阶段的猪对温度要求还不一样。冬天为了保温门一关窗一闭氨气浓度蹭蹭往上涨。氨气是猪舍里最常见的恶臭气体主要来自粪便和垫料发酵浓度超过20ppm就会持续刺激猪的呼吸道黏膜时间一长猪就容易咳嗽、流泪生长速度明显变慢。我见过不少散养户冬天舍不得开风机猪舍里氨气浓度冲到三四十ppm人推门进去眼睛都睁不开猪遭的罪可想而知。湿度同样不能忽略长期高于85%会加重病原菌滋生太低了又容易诱发粉尘和呼吸道问题。而人工管理最大的问题在于——人不可能24小时盯着偏偏很多事故就是发生在下半夜气候突变的时候。基于这些实际矛盾整套系统的设计目标就清晰了实时采集环境参数自动控制排风机、加热器、喂料器、饮水电磁阀再通过物联网云平台把数据和报警推送到手机上就算人在几公里外也能掌握猪舍动态。1.2 主控方案为什么选STM32项目立项时我把主流方案摆在一起比过STM32F103C8T6、ESP32、树莓派Zero。三者的对比直接看表方案成本实时性生态资料环境耐受适合场景STM32F103C8T6核心板十几元高中断响应快极其丰富例程满天飞工业级芯片耐温范围宽传感器采集、电机控制、多外设聚合ESP32板子二十几元中WiFi协议栈干扰时延不稳定偏物联网方向WiFi射频受温湿度影响略大快速原型、纯无线场景树莓派Zero百元以上低跑Linux有调度延迟偏软件生态长时间通电对SD卡不友好断电容易坏文件系统图像识别等重计算场景最终我选了STM32F103C8T6原因很直接它不需要跑操作系统裸机代码反而简单可控传感器采集、继电器控制、步进电机驱动这些任务用定时器和中断就能安排得明明白白。它的GPIO、ADC、USART资源富余以后想加CAN总线扩展多猪舍联动也留得住余地。最关键是资料全不管遇到了DHT22读不到数据、ILI9341屏幕花屏、还是ADC采集值跳来跳去网上都有前人的坑和解决方案这对一个从零搭建的工程来说太重要了。1.3 传感器选型思路温湿度环节我在DHT22和SHT30之间犹豫过。DHT22便宜、例程多但它是单总线协议时序要求非常苛刻主频稍一波动就容易读失败SHT30走I2C精度和一致性更好价格也就高几块钱。项目最终选SHT30省心。如果只是为了低预算跑通DemoDHT22也不是不行但一定要把延时函数写好。氨气检测这里要重点提醒一下。最开始我用的是MQ-135这个传感器便宜但缺点很致命需要预热数小时才能稳定并且输出值受温湿度影响很大直接拿ADC原始量程套公式换算浓度结果很可能误导控制逻辑。后来换了ZE03电化学式氨气传感器模块串口TTL直接输出ppm数值出厂做过校准稳定性和精度都靠谱得多。预算允许的情况下环境气体类传感器建议优先选带数字输出的电化学式或红外式模块别在模拟量传感器上反复折腾校准。料位检测用HC-SR04超声波模块装在料仓顶部朝下测料面距离。水位检测用的是浮球开关一只低液位报警一只高液位停补水结构简单、误报率低比电极式耐脏污。2. 系统整体架构与硬件设计2.1 系统拆解与引脚分配整套系统从功能上分四层感知层负责采数据决策层由STM32负责逻辑判断执行层包括继电器、步进电机和电磁阀交互层就是本地屏幕加按键再加上ESP8266模块与云端联动。这样一个结构既不复杂又能把嵌入式项目的核心要素全部覆盖到。硬件型号确定后我先列了一张引脚分配表再动手接线避免后面发现引脚冲突返工。表格里给出我实际使用的分配方案供参考外设模块引脚说明SHT30温湿度PB6 / PB7I2C1上拉4.7kΩZE03氨气PA2 / PA3串口2接收TTL电平HC-SR04超声测距PA0触发 / PA1回波用于料位监测继电器1排风机PB0光耦隔离低电平触发继电器2加热器PB1光耦隔离低电平触发继电器3饮水电磁阀PB2光耦隔离ULN2003驱动IN1~IN4PA8~PA11接28BYJ-48步进电机下料限位开关PA12喂料机构归零检测ESP8266PA9 / PA10串口1波特率115200本地按键PB3 / PB4 / PA15需禁用JTAG释放引脚OLED/LCD屏SPI接口PB13~PB15本地状态显示这里有一个特别容易被坑的点PB3、PB4、PA15默认是JTAG调试引脚直接用GPIO会不生效。解决办法是在初始化代码里调用禁用JTAG的库函数释放这三个引脚。我当时按键不够用就是靠放出这三根引脚解决的否则只能换其他引脚布局全乱。2.2 电源与继电器隔离设计整套设备的电源链路是220V交流经开关电源转12V再通过降压芯片转5V最后稳压到3.3V给主控和传感器供电。供电顺序和隔离设计我都花了心思继电器部分必须用光耦隔离。MCU的IO电平直接驱动继电器线圈会带来两个问题一是线圈反峰电压可能倒灌击穿引脚二是继电器吸合瞬间的电流抖动会拉低电源导致ADC采样数据毛刺甚至主控复位。具体电路做法是IO通过限流电阻接光耦输入端光耦输出侧用三极管驱动继电器线圈线圈两端并联续流二极管和RC吸收回路。光耦选用PC817就够用。模拟部分和数字部分的电源地线要单点连接。SHT30和氨气传感器属于模拟信号如果直接和继电器数字地大面积共地开关动作瞬间的地电位波动会让你抓狂。我是把模拟地和数字地在主控附近用一个0Ω电阻单点汇接实测ADC数据干净很多。2.3 本地显示与ILI9341的坑本地显示我用的是2.4寸ILI9341驱动的SPI屏。安装驱动时遇到一个很典型的坑——读ID读回来是0xA1A1并不是手册里标准的0x9341。查了一圈发现很多国产兼容屏的ID寄存器本来就不标准读回来的值根本不可信。解决办法是不必死磕芯片ID直接用厂家提供的初始化序列初始化屏幕液晶照样正常显示。以后大家遇到这类问题先怀疑屏的兼容性而不是怀疑自己的初始化代码。屏幕在调试阶段的价值比很多人想象中更大它能把温度、湿度、氨气浓度、风机状态、下料次数直接显示出来不用每次都接电脑看串口尤其是设备挂在猪舍现场时本地状态一目了然。按键加屏幕就是一个人机交互入口配置阈值参数、手动切换喂料模式都能在本地完成。2.4 按键防抖和状态指示按键电路设计看似简单做不好同样闹心。每个独立按键都接10kΩ上拉电阻到3.3V按键按下拉低MCU读到低电平。软件里做20ms消抖状态变化后只触发一次动作。同时留了一组状态LED一个指示网络连接状态一个指示系统运行心跳现场排查问题的时候比什么都管用。3. 下位机软件架构与核心逻辑3.1 代码组织与任务调度整套下位机代码我没有上RTOS因为任务数量有限环境数据采集、控制逻辑、喂料、屏幕刷新、网络上报加一起不超过十个任务裸机主循环完全转得过来。上了RTOS反而增加调度切换的开销和排查问题的复杂度。我的做法是采用时间片轮询。用一个1ms的SysTick基准时间戳主循环里用一个调度表每10ms刷新一次按键、每100ms读一次传感器、每500ms执行一次温控逻辑、每1s刷新屏幕、每30s上报一次云端数据。这种结构清晰、调试简单因为每个任务都在固定的时间窗口内运行出问题很容易通过串口打印定位。关键部分SysTick中断里不要做耗时操作只负责累加时钟变量。延时函数卡死的问题十有八九和SysTick被高优先级中断抢占有关后面调试实录里我再详细讲。3.2 ADC采集与数据滤波ZE03氨气传感器直接走串口读ppm数值省事但SHT30的温湿度走I2C读取超声波测距模块是用定时器捕获回波脉宽。ADC采集主要用在电流采样和气压的扩展预留上但滤波方法还是值得说一说。ADC采集我采用中值滤波加滑动平均结合的方式连续采9次排序后取中间5个值再求平均。别小看这一步未做滤波时数据显示能跳十几个LSB滤波后稳定在±2个LSB。对于环境量不需要太高的采样率100ms采一轮足够。超声波测距用于料位我做了更聪明的处理连续测5次去掉最大最小再取平均并将单次回波超过2m的数据判定为无效测量。否则料仓里粉尘和小颗粒飞散会带来随机回波导致料位一会儿高一会儿低。3.3 温度滞回控制逻辑温度控制用PID还是用经验阈值我的结论是这套系统不上PID用滞回控制更合适。猪舍是一个大惯性对象温度变化非常慢PID参数调不好不但控制不稳还容易让风机和加热器频繁启停缩短继电器寿命。滞回控制的思路很简单设定温度下阈值和上阈值比如成年猪的舒适区我设下限18℃、上限26℃。低于下限开启加热器并保持低风速循环高于上限启动排风机大风量降温处于上下限之间就维持弱通风。加一层滞回是为了避免温度在阈值边缘来回抖动导致执行器频繁切换。代码逻辑示意如下typedef struct { float temp; // 当前温度 float low; // 下限阈值 float high; // 上限阈值 uint8_t state; // 0等待 1加热 2排风 } EnvCtrl_t; void EnvControl_Task(EnvCtrl_t *env) { if (env-temp env-low) { env-state 1; Heater_Set(100); // 全功率加热 Fan_Set(30); // 低风量热风循环 } else if (env-temp env-high) { env-state 2; Heater_Set(0); Fan_Set(100); // 全速排风 } else { if (env-state 2) { Fan_Set(30); // 降温到位后减少能耗 } else if (env-state 1) { Heater_Set(50); // 升温到位后降低加热功率 } } }排风机的转速直接用PWM控制这样既能根据温度变化平滑调速又能省电。风机转速反馈如果要用闭环可以用定时器外部中断对霍尔脉冲计数在固定时间窗内数脉冲换算转速。这种测频率的方法比输入捕获简单且抗干扰注意对脉冲做一下软件消抖就行。3.4 步进电机喂料与RTC定时喂料机构采用28BYJ-48步进电机加ULN2003驱动板。为什么要用步进电机因为投料需要精确的圈数来控制出料量普通直流电机会因为负载和电压波动导致过量或不足。28BYJ-48是减速步进电机扭矩足够带动下料螺旋速度慢但精确正符合喂料场景。软件上我写了一个四相八拍驱动序列每拍之间加延时控制速度const uint8_t step_table[8][4] { {1,0,0,0}, {1,1,0,0}, {0,1,0,0}, {0,1,1,0}, {0,0,1,0}, {0,0,1,1}, {0,0,0,1}, {1,0,0,1} }; void Feed_RotateSteps(uint16_t steps) { for (uint16_t i 0; i steps; i) { uint8_t idx i % 8; HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, step_table[idx][0]); HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, step_table[idx][1]); HAL_GPIO_WritePin(IN3_GPIO_Port, IN3_Pin, step_table[idx][2]); HAL_GPIO_WritePin(IN4_GPIO_Port, IN4_Pin, step_table[idx][3]); delay_us(800); } }喂料时间用RTC定时。STM32内部RTC掉电后时间会丢我干脆外挂了DS3231高精度时钟模块带后备电池断电后时间依然准确。每天设定三个喂料时间点8点、12点、18点。每次喂料前先让步进电机反转至限位开关复位再正转指定步数下料保证每次起始位置一致下料量不会越积越多。3.5 看门狗与异常复位工业现场设备最怕跑飞了没人管所以在系统里加了独立看门狗IWDG超时时间设2秒。主循环里每500ms喂一次狗只要某个任务卡死超过2秒就自动复位重启。注意喂狗时机不能放在中断里否则主循环死掉中断照样喂狗看门狗就形同虚设了。4. 远程监控与云端联动4.1 为什么选择巴法云自建服务器做远程监控是最折腾的路线不仅要有固定公网IP或者内网穿透还要维护服务器安全对于单猪舍的小项目完全不划算。巴法云这类物联网云平台的好处是免费、接入门槛低、设备接入和消息推送流程都是现成的非常适合中小型项目快速落地。4.2 ESP8266接入云端的配置流程ESP8266模块在这个项目里承担网络接入角色我用的是1MB Flash版本刷AT固件。配置流程分四步设置工作模式ATCWMODE3StationSoftAP实际只用到Station模式SoftAP留作备用调试。连接WiFiATCWJAPSSID,PASSWORD成功后模块会返回WIFI CONNECTED。连接MQTT服务器用AT指令或专用的MQTT透传指令连接巴法云服务器地址和端口。主题订阅和发布巴法云里创建Topic注意要另创建私钥SetTopic用于设备认证上报时向主题发布JSON格式的数据。ESP8266供电问题一定要重视。很多掉线、重启、连不上问题都是供电不足导致的。ESP8266在WiFi发射瞬间电流波动很大直接从主控的3.3V输出取电容易电压跌落正确做法是单独用一块AMS1117-3.3线性稳压给ESP8266供电且就近并联一个470μF电解电容增强瞬态响应。4.3 数据上报与掉线重连云端数据字典我在项目里定义成JSON格式{temp:24.5,humi:61.0,nh3:8.0,feed:200,water:75}字段含义温度、湿度、氨气浓度ppm、剩余料量百分比、水位百分比。主控每30秒通过串口发送一条MQTT消息到巴法云主题手机端小程序订阅同一主题即可实时刷新。掉线重连逻辑是远程监控稳定性的关键。程序里用一个状态机维护ESP8266连接状态正常上报状态下如果发送失败计数超过3次就切换到重连状态先发送ATCWJAP重新连WiFi再重新建立MQTT连接直到恢复为止。同时维持一个心跳包每30秒发一次确保云端能及时感知设备存活状态。4.4 告警推送配置报警逻辑我做了双重保障。第一层是本地下限位判断温度超过上限或氨气超过设定值时现场蜂鸣器和报警灯立刻响应。第二层是云端推送巴法云主题支持Webhook回调我在后台配置了消息转换规则当接收到的数据里温度或氨气超出阈值时调用微信推送服务把报警消息推送到手机。这套组合拳至少在两个维度防止漏报现场有声光、手机有推送。有一次半夜氨气探头数值飙到报警线我手机收到推送后远程开启了排风机大风量模式二十分钟后数值降到安全范围整个过程没下床这就是远程监控存在的意义。5. 现场安装与机械结构改造5.1 传感器布点原则硬件做好不代表项目完工传感器布点直接决定数据有没有参考价值。温度湿度传感器装在猪舍中部离地面1.2~1.5米高度避开风机直吹区域和太阳直射位置否则测出来的是局域温度而不是环境温度。氨气传感器装得离粪沟或漏粪板近一些因为氨气主要从这些地方挥发但同样不能泡在粪污喷溅范围里需要加防护罩防溅水。最优做法是在猪舍对角线位置布置两个温湿度测点软件里取平均值参与控制避免单点失效时出现控制盲区。实测下来单点测温和双点均值的最大偏差能有3~4℃在冬季尤其明显。5.2 下料机构与饮水改造下料机构我选的是螺旋给料器方案。步进电机带动螺旋轴旋转时把料仓里的饲料挤到食槽端。这个方案的优点是下料量可控、饲料不易结拱堵塞。限制位开关装在螺旋轴初始位置每次喂料先归零再正转防止累计误差导致越下越多。饮水电磁阀是常闭型12V电磁阀串联在供水管路上由继电器控制。软件里设置饮水时段控制逻辑每天6~22点之间如果料槽缺水则自动补水晚上则关闭电磁阀防止饮水器漏水淹圈舍。如果还需要更精细的水位监测可以再加投入式液位传感器但在基础版项目里浮球开关加电磁阀的组合已经足够。5.3 走线与防水防护猪舍环境高湿、有腐蚀性气体走线防护是项目成败的关键。我的处理方式所有接线端子打在密封防水接线盒内焊点套热缩管PCB板表面喷三防漆传感器外壳加装防护罩。信号线用屏蔽线屏蔽层单端接地动力线和信号线分开走线槽间距至少20厘米否则电机启动瞬间强干扰会让I2C总线通信异常。6. 调试实录高频问题与解决速查表6.1 由简到繁的调试顺序任何复杂的嵌入式项目都不要一上来全系统联调。我的调试顺序是先最小系统再逐模块点亮最后联调先烧一个LED闪烁程序确认芯片、时钟、调试器正常。用串口打印“Hello”确认USART通路。单独读SHT30打印温湿度。单独读ZE03打印氨气浓度。触发继电器听吸合声测触点输出。转步进电机看下料动作。ESP8266单独接电脑调通AT指令确认联网。最后才把所有模块集成到同一套代码里。每走一步都验证一步问题出现时就能锁定在刚接入的那个模块上而不是在整片代码泥潭里捞针。6.2 高频问题与排查方法下面把调试中遇到的高频问题整理成速查表每一条都是实际踩过的坑现象可能原因解决办法延时函数卡死SysTick中断优先级被更高优先级中断抢占或中断里做了耗时操作把SysTick设为最低优先级中断里只置标志位别做耗时逻辑ADC读数乱跳模拟地数字地未分开或采样频率太高单点接地连续采样做中值平均滤波I2C一直读不到数据SDA被拉死、上拉电阻缺失、地址错误检查上拉电阻4.7kΩ用扫描脚本探测设备地址ILI9341读ID返回0xA1A1国产兼容屏ID寄存器不标准不读ID直接用厂家初始化序列初始化MQ-135数值漂移预热不充分受温湿度影响预热数小时再校准或改用ZE03数字输出模块ESP8266频繁掉线供电不足或WiFi信号弱独立供电加470μF电容天线远离金属结构JTAG引脚当GPIO无效默认被调试功能占用调用禁用JTAG释放PB3/PB4/PA15引脚继电器吸合时主控复位线圈反峰干扰电源加光耦隔离续流二极管RC吸收去耦电容喂料量越下越多步进电机未归零导致累计误差每次喂料前反转至限位开关归零看门狗频繁复位任务执行时间超过喂狗周期缩短单任务处理时长或加大喂狗间隔6.3 完整排查案例拿最头疼的一次故障举例系统在猪舍运行两天后突然每隔几个小时就自动重启一次。起初怀疑是看门狗触发串口日志却没有任何异常打印。后来把复位原因定位到硬件看门狗之外发现主控板供电电压在风机启动瞬间掉到3.1V左右这个电压刚好触发芯片的欠压复位。排查过程是把示波器挂在供电节点触发风机吸合动作捕捉到几十毫秒的电压跌落。根本原因是风机继电器直接串在5V电源轨上风机启动电流大把5V拉垮了。解决方法是把风机供电改为单独12V回路直接驱动主控5V和风机隔离问题彻底消失。这件事的教训是功率执行器件一定不要和主控共用同一路电源宁可多走一根线。7. 复盘与后续扩展整套系统做完我个人最深的体会是这种“采集—控制—远程联动”的完整链路远比单写一个驱动或算法更有价值。它不是那种跑个流水灯就结束的Demo而是每一层都有真实工程问题需要解决。硬件要懂隔离和接地软件要懂任务调度和容错现场安装要懂环境和防护这一套走下来对嵌入式综合能力的提升非常明显。如果后续要继续扩展我琢磨过几条路线一是把温控逻辑升级成模糊PID或模型预测控制让温度更平稳二是接入摄像头和K210做猪只计数、行为异常识别甚至通过图像判断猪的体况评分三是在主控上把USB口做成虚拟串口或U盘模式现场拷贝历史数据曲线方便做生长周期复盘。这些都是基于现有硬件框架就能渐进做完的事。关于这套基于STM32的智慧养猪系统我能分享的核心就这些。设计资料、代码和接线图都在手头整理了完整备份遇到具体问题欢迎直接聊。做这类项目技术方案可以千变万化但底层的排查思路和工程习惯是共通的希望对准备动手的朋友有所帮助。
返回列表