1. 项目缘起与整体设计思路
1.1 为什么选择STM32做污水检测船的主控
做水质监测这个方向,我前前后后折腾过好几套方案。最早用树莓派,算力是够,但功耗和成本摆在那里,野外部署要配大容量电池,整体下来一套轻松过千。后来试过Arduino,简单是简单,但多传感器并发采集的时候时序经常出问题,ADC精度也不够看。最后落到STM32F103系列上,算是找到了一个平衡点——性能够用、功耗可控、外设丰富、成本压得住。
STM32F103C8T6这颗芯片,72MHz主频,内置12位ADC,多达10个外部通道,USART、I2C、SPI一应俱全。对于污水检测船这种需要同时接pH传感器、浊度传感器、温度传感器、GPS定位模块和无线传输模块的场景来说,外设资源刚好够用,不会捉襟见肘。更重要的是,它的低功耗模式做得比较成熟,Stop模式下电流能压到20微安级别,这对靠电池驱动的小型船体来说非常关键。
便携式这个定位决定了整个系统的设计基调。所谓便携,不是说揣兜里就走,而是指一个人能搬得动、放得下、收得快。船体不能太大,传感器不能太重,电池续航要撑得住至少半天的连续作业。这些约束条件反过来倒逼主控选型必须走低功耗、小体积、高集成度的路线,STM32恰好卡在这个位置上。
1.2 系统整体架构拆解
整个污水检测船可以拆成五个功能模块来理解:感知层、控制层、通信层、动力层和供电层。感知层负责采集水质参数,控制层负责数据处理和逻辑调度,通信层负责把数据传回来,动力层负责让船动起来,供电层负责给所有模块喂电。
感知层这边,我选了三种传感器:pH传感器用模拟输出的工业级探头,浊度传感器用红外对射式模块,温度传感器用DS18B20数字探头。为什么这么搭配?pH和浊度需要实时连续采集,模拟输出响应快;温度变化相对缓慢,用数字接口的DS18B20可以省一个ADC通道,而且精度比模拟方案更稳定。
控制层就是STM32最小系统板加上必要的外围电路。这里有个细节值得展开说:ADC参考电压的稳定性直接决定pH和浊度读数的可信度。我一开始直接用STM32的3.3V供电做参考,结果电机一启动,读数就飘。后来单独用了一颗REF3033给ADC做基准,问题才解决。这个坑后面会详细讲。
通信层我选的是ESP8266模块走WiFi,通过UART和STM32通信。为什么不用4G?因为便携式设备大概率在近岸或者小型水域作业,WiFi覆盖基本够用,而且ESP8266成本低、功耗小、AT指令集成熟,开发周期短。如果后续要扩展到远距离作业,再换4G模块也不迟,接口是兼容的。
动力层用两个直流减速电机加一个L298N驱动模块,差速转向。船体用亚克力板做双层结构,下层放电池和电机,上层放电路板和传感器,中间用铜柱撑开。这样重心低,不容易翻。
供电层用3节18650锂电池串联,标称11.1V,经过LM2596降压到5V给电机驱动和传感器供电,再经过AMS1117-3.3降到3.3V给STM32和ESP8266供电。电池容量选的是3000mAh,实测下来连续作业能撑4到5个小时,基本满足半天的工作需求。
1.3 方案选型中的几个关键取舍
第一个取舍是传感器接口方案。pH传感器有模拟输出的,也有RS485数字输出的。RS485抗干扰能力强,但需要额外的转换芯片,而且布线麻烦。模拟输出简单直接,但对ADC参考电压和滤波要求高。我最终选了模拟方案,原因是船体空间有限,少一个模块少一份重量,而且通过软件滤波和硬件基准,精度也能做到±0.1pH,够用了。
第二个取舍是通信协议。ESP8266支持TCP和UDP两种方式。TCP可靠但有重传机制,延迟不稳定;UDP快但可能丢包。水质数据不是每一帧都关键,丢一两帧不影响整体趋势判断,所以我选了UDP,配合应用层的简单序号校验,兼顾了实时性和可靠性。
第三个取舍是船体推进方式。单电机加舵机转向结构简单,但转向半径大,在小水域不好掉头。双电机差速转向灵活,原地就能转圈,但控制逻辑稍微复杂一点。考虑到污水检测经常需要在狭窄河道或者池塘里作业,灵活性优先,所以选了双电机方案。
2. 核心硬件细节与实操要点
2.1 STM32最小系统与外围电路设计
STM32F103C8T6最小系统板市面上很多,但质量参差不齐。我踩过的坑是:有些板子的晶振负载电容焊错了,导致起振不稳定,跑着跑着就死机。所以拿到板子第一件事,先用示波器看晶振波形,确认8MHz晶振起振正常,波形干净没有明显畸变。
外围电路这边,有几个地方需要特别注意。首先是BOOT0和BOOT1引脚,一定要接下拉电阻到地,否则上电时可能误入Bootloader模式,程序不运行。其次是NRST复位引脚,接一个0.1uF电容到地,再加一个10K上拉电阻到3.3V,保证复位可靠。最后是VDDA和VSSA,也就是模拟电源引脚,一定要加LC滤波,否则ADC读数会有周期性纹波。
ADC输入这边,pH传感器输出阻抗比较高,直接接STM32的ADC引脚会导致采样保持电容充电不足,读数偏低。我加了一级电压跟随器,用LM358运放做缓冲,输出阻抗降到几十欧姆,ADC读数就准了。浊度传感器输出阻抗低一些,但也建议加一级RC低通滤波,截止频率设在100Hz左右,滤掉电机带来的高频干扰。
2.2 传感器选型与校准方法
pH传感器我用的是一款工业级玻璃电极,输出0到3V对应pH 0到14。这里有个常见误区:很多人以为pH电极是线性的,直接拿两点校准就完事。实际上玻璃电极在强酸强碱区域会有非线性偏差,如果检测场景pH波动范围大,建议做三点甚至五点校准。
校准步骤是这样的:先用pH 4.00、6.86、9.18三种标准缓冲液,分别记录ADC读数,然后在STM32里用分段线性插值的方式拟合曲线。具体做法是存三个校准点,运行时判断当前ADC值落在哪个区间,用对应区间的斜率和截距计算pH值。这样比单段线性拟合精度高不少,实测误差能控制在±0.05pH以内。
浊度传感器我用的是红外对射式模块,输出模拟电压。这个传感器的标定比较麻烦,因为浊度单位NTU没有绝对标准。我的做法是用福尔马肼标准液配制不同浓度的样品,从0NTU到1000NTU取十个点,记录ADC读数,然后在Excel里拟合曲线。拟合出来是一条指数衰减曲线,在STM32里用查表加线性插值的方式实现。
DS18B20温度传感器是数字输出的,精度±0.5°C,够用。接线的时候注意加一个4.7K上拉电阻到3.3V,否则单总线通信会不稳定。另外DS18B20的转换时间比较长,12位精度下需要750ms,所以我在程序里用定时器触发转换,不阻塞主循环。
2.3 电源管理与低功耗设计
便携式设备最怕的就是电不够用。我一开始用LM2596降压到5V,再线性降压到3.3V,结果发现AMS1117发热严重,效率只有60%左右。后来改成两级开关降压:第一级LM2596降到5V,第二级用MP1584降到3.3V,整体效率提到85%以上,发热也小了很多。
低功耗方面,STM32本身支持Sleep、Stop和Standby三种模式。我的策略是:传感器采集间隙让STM32进Stop模式,RTC定时唤醒,这样平均电流能从30mA降到5mA左右。ESP8266在不发送数据的时候也进Modem-sleep模式,电流从70mA降到15mA。整体算下来,3000mAh电池能撑6个小时以上。
注意:进Stop模式前一定要把不用的外设时钟关掉,GPIO配置成模拟输入或者下拉,否则漏电流会吃掉不少电量。我实测过,一个悬空的GPIO在Stop模式下能多耗几百微安。
2.4 通信模块配置与数据协议设计
ESP8266用AT指令配置,固件版本建议用AT 1.7以上,稳定性好很多。配置流程是:先AT测试通信,然后AT+CWMODE=1设成Station模式,AT+CWJAP连接热点,AT+CIPSTART建立UDP连接,最后AT+CIPSEND发送数据。
数据协议我设计了一个简单的帧结构:帧头0xAA 0x55,然后是一字节序号,一字节数据长度,接着是pH、浊度、温度、经纬度等数据,最后是校验和。校验和用前面所有字节的异或值。接收端收到数据后先检查帧头和校验和,都对了才解析。
为什么不用JSON?因为JSON解析在STM32上开销太大,而且字符串传输容易出错。二进制协议紧凑、解析快、抗干扰能力强,适合这种资源受限的场景。实测下来,一帧数据大概40字节,UDP发送延迟在50ms以内,完全满足实时性要求。
3. 软件架构与核心代码实现
3.1 主程序框架与任务调度
STM32这边的程序我没有用RTOS,因为任务不算多,用前后台架构加定时器调度就够了。主循环里轮询三个任务:传感器采集、数据处理、通信发送。每个任务用一个软件定时器控制执行周期,采集任务100ms一次,处理任务200ms一次,发送任务500ms一次。
为什么这么分配?pH和浊度需要快速响应,100ms采集一次能捕捉到变化趋势;数据处理包括滤波和校准计算,200ms一次足够;通信发送不需要太频繁,500ms一次既能保证实时性,又不会把网络带宽占满。
定时器我用的是SysTick,配置成1ms中断一次,在中断里维护三个计数器,分别对应三个任务的周期。主循环里检查计数器是否到期,到期就执行对应任务,然后清零计数器。这种方式的优点是简单可靠,不需要复杂的任务调度器。
3.2 ADC采集与数字滤波实现
ADC采集这边,我用了DMA加定时器触发的方式。TIM2配置成100Hz更新频率,每次更新触发ADC转换,转换结果通过DMA自动搬到内存数组里。这样CPU不用干预,效率高,而且采样间隔精确。
采集到的原始数据不能直接用,必须滤波。我用了两种滤波组合:先做中值滤波,取最近5个采样值的中位数,去掉突发干扰;再做滑动平均,取最近10个中位数的平均值,平滑随机噪声。实测下来,这种组合滤波能把pH读数的波动从±0.3pH压到±0.05pH以内。
代码实现上,中值滤波用一个5元素数组,每次新数据进来就移位,然后排序取中间值。滑动平均用一个10元素环形缓冲区,每次新数据进来就替换最老的数据,然后求和取平均。这两个操作计算量都不大,在72MHz的STM32上跑起来毫无压力。
#define MEDIAN_SIZE 5 #define AVERAGE_SIZE 10 float median_filter(float new_val) { static float buf[MEDIAN_SIZE] = {0}; static uint8_t idx = 0; float temp[MEDIAN_SIZE]; buf[idx] = new_val; idx = (idx + 1) % MEDIAN_SIZE; for (int i = 0; i < MEDIAN_SIZE; i++) { temp[i] = buf[i]; } // 冒泡排序 for (int i = 0; i < MEDIAN_SIZE - 1; i++) { for (int j = 0; j < MEDIAN_SIZE - 1 - i; j++) { if (temp[j] > temp[j + 1]) { float t = temp[j]; temp[j] = temp[j + 1]; temp[j + 1] = t; } } } return temp[MEDIAN_SIZE / 2]; }3.3 数据校准与单位换算
传感器原始数据到物理量的换算,是整个系统精度的关键。pH这边,我用的是分段线性插值。先存三个校准点:(adc1, ph1)、(adc2, ph2)、(adc3, ph3),运行时判断当前ADC值落在哪个区间,用对应区间的斜率和截距计算。
浊度这边更复杂一些,因为拟合出来是指数曲线。我的做法是在STM32里存一个查找表,比如每50NTU存一个点,从0到1000NTU共21个点。运行时先找到当前ADC值落在哪个区间,然后用线性插值计算NTU值。这样既保证了精度,又不会占用太多计算资源。
温度这边DS18B20直接输出数字量,不需要换算,但要注意分辨率配置。默认是12位,精度0.0625°C,转换时间750ms。如果对实时性要求高,可以降到9位,转换时间93.75ms,精度0.5°C。我选的是11位,转换时间375ms,精度0.125°C,算是一个平衡。
3.4 通信协议封装与发送逻辑
通信这块,ESP8266通过UART和STM32连接,波特率115200。STM32这边用USART2,配置成异步模式,开启接收中断。发送的时候先把数据打包成帧,然后通过AT+CIPSEND指令发送。
帧结构定义如下:
| 字段 | 长度 | 说明 |
|---|---|---|
| 帧头 | 2字节 | 0xAA 0x55 |
| 序号 | 1字节 | 0-255循环 |
| 长度 | 1字节 | 数据段长度 |
| pH值 | 4字节 | float类型 |
| 浊度值 | 4字节 | float类型 |
| 温度值 | 4字节 | float类型 |
| 经度 | 4字节 | float类型 |
| 纬度 | 4字节 | float类型 |
| 校验和 | 1字节 | 前面所有字节异或 |
发送逻辑是这样的:先检查ESP8266是否在线,发送AT测试,收到OK后发送AT+CIPSEND=帧长度,收到>后发送帧数据,等待SEND OK确认。如果任何一步超时,就重试,重试三次都失败就复位ESP8266。
实操心得:ESP8266在发送数据的时候,如果电源不稳,很容易重启。我一开始用AMS1117给它供电,结果一发数据就重启。后来单独用一个MP1584给它供电,问题就解决了。所以ESP8266的供电一定要独立,而且要有足够的滤波电容。
4. 船体结构与动力系统搭建
4.1 船体材料选择与防水处理
船体材料我试过三种:泡沫板、亚克力和PVC管。泡沫板最轻,但强度不够,撞到石头就碎;PVC管防水好,但形状受限,不好布置电路板;亚克力强度够、加工方便、透明好看,最终选了5mm厚的亚克力板。
船体尺寸是40cm长、25cm宽、15cm高,双层结构。下层高8cm,放电池、电机和驱动板;上层高7cm,放STM32主板、传感器和通信模块。两层之间用M3铜柱撑开,间距5cm,方便走线。
防水处理是重点。所有接缝处先用亚克力胶水粘合,然后在内侧涂一层704硅胶。电路板用防水盒装起来,出线孔用防水接头密封。传感器探头固定在船体底部,接线从防水接头穿上来。电机轴伸出船体的地方,用O型密封圈加黄油密封。
实测下来,这套防水方案在静水中泡两个小时没问题。但如果要在有波浪的水面作业,建议再加一层防水罩,把整个上层结构罩起来。
4.2 双电机差速转向控制
动力系统用两个直流减速电机,额定电压12V,减速比1:48,空载转速200RPM。电机固定在船尾两侧,螺旋桨朝后。L298N驱动模块负责控制电机正反转和调速。
差速转向的原理很简单:两个电机同速正转,船直行;左电机慢右电机快,船右转;左电机反转右电机正转,船原地左转。PWM频率我设的是10kHz,占空比0到100%对应电机速度0到最大。
控制逻辑上,我用了一个简单的PID控制器来维持航向。MPU6050陀螺仪提供偏航角速度,目标航向由遥控指令或者预设航线决定。PID输出作为左右电机的速度差,叠加到基础速度上。实测下来,直线航行偏差能控制在±5度以内。
// 差速转向控制 void motor_control(int16_t left_speed, int16_t right_speed) { // 限制速度范围 if (left_speed > 100) left_speed = 100; if (left_speed < -100) left_speed = -100; if (right_speed > 100) right_speed = 100; if (right_speed < -100) right_speed = -100; // 设置方向 if (left_speed >= 0) { GPIO_SetBits(GPIOA, GPIO_Pin_0); // 左电机正转 TIM_SetCompare1(TIM3, left_speed); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 左电机反转 TIM_SetCompare1(TIM3, -left_speed); } if (right_speed >= 0) { GPIO_SetBits(GPIOA, GPIO_Pin_1); // 右电机正转 TIM_SetCompare2(TIM3, right_speed); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_1); // 右电机反转 TIM_SetCompare2(TIM3, -right_speed); } }4.3 电池组配置与续航估算
电池用3节18650串联,标称11.1V,容量3000mAh。为什么选18650?因为能量密度高、放电倍率够、价格便宜、更换方便。三节串联后电压11.1V,经过LM2596降到5V给电机驱动和传感器,再经过MP1584降到3.3V给STM32和ESP8266。
续航估算:电机满载电流约1.5A,STM32加传感器约50mA,ESP8266平均约30mA,总电流约1.58A。电池容量3000mAh,理论续航1.9小时。但实际使用中电机不会一直满载,平均电流大概1A左右,所以实际续航能到3小时左右。
如果想延长续航,有两个办法:一是加大电池容量,换成4节并联再串联,容量翻倍;二是优化电机控制,低速时用PWM降速,减少电流消耗。我实测过,把电机速度降到50%,电流从1.5A降到0.6A,续航能延长到5小时以上。
注意:18650电池一定要用带保护板的,否则过放会损坏电池,甚至起火。我一开始图便宜买了不带保护的电池,结果有一次放到2.5V,电池直接鼓包了。后来换了带保护板的,过放到2.8V就自动切断,安全多了。
4.4 遥控与自主导航模式切换
遥控这块我用的是NRF24L01模块,2.4GHz频段,空旷环境下传输距离能到100米。遥控器这边用STM32F103加摇杆和按键,摇杆控制方向和速度,按键切换模式。
模式有两种:手动模式和自动模式。手动模式下,遥控器直接发送速度和转向指令,船体执行。自动模式下,船体按照预设航线自主航行,遥控器只负责启动和停止。
自动导航的实现是这样的:先用GPS模块获取当前位置,然后和目标航点比较,计算航向偏差,用PID控制器调整电机速度差,使船体朝目标航点前进。到达目标航点后,切换到下一个航点,直到所有航点走完。
GPS模块我用的是ATGM336H,支持GPS和北斗双模,定位精度2.5米。这个精度对于水质检测来说够用了,因为水质参数在几米范围内变化不大。如果对定位精度要求更高,可以上RTK,但成本会高很多。
5. 常见问题与排查技巧实录
5.1 传感器读数漂移与噪声排查
传感器读数漂移是最常见的问题,我遇到过好几次。第一次是pH读数一直缓慢上升,从7.0漂到8.5,换了传感器也没用。后来用万用表量ADC参考电压,发现从3.300V慢慢降到3.280V,原来是AMS1117发热导致输出电压漂移。换了MP1584之后,参考电压稳定在3.300V,漂移问题解决。
第二次是浊度读数跳变,一会儿100NTU一会儿500NTU。用示波器看ADC输入引脚,发现上面叠加了100Hz的纹波,正好是电机PWM频率的谐波。解决办法是在ADC输入和地之间加一个10uF钽电容,再串一个100欧姆电阻,组成低通滤波器,纹波就没了。
第三次是温度读数偶尔跳到85°C,这是DS18B20的典型故障值。原因是单总线通信时序不对,可能是上拉电阻太大或者线太长。我把上拉电阻从10K换成4.7K,线缩短到20cm,问题就解决了。
5.2 通信中断与数据丢包处理
ESP8266通信中断也是高频问题。表现是数据发着发着就停了,重启ESP8266又能恢复。排查下来有几个原因:一是电源不稳,ESP8266发送瞬间电流能到300mA,如果电源响应慢,电压会跌落导致重启;二是AT指令超时设置太短,ESP8266还没响应就判超时;三是WiFi信号弱,丢包严重。
解决办法:电源这边加一个大电容,我用了470uF电解电容并联0.1uF陶瓷电容,电压跌落问题解决。AT指令超时从1秒改成3秒,给ESP8266足够的响应时间。WiFi信号弱的话,加一个外置天线,或者把船开到信号好的地方。
数据丢包这边,我在应用层加了序号校验。接收端发现序号不连续,就知道中间丢包了,可以请求重发或者标记数据缺失。实测下来,UDP丢包率在5%左右,加了序号校验后,数据完整性提高到99%以上。
5.3 电机干扰与电源纹波抑制
电机干扰是嵌入式系统里的经典问题。电机启动瞬间,电流突变,会在电源线上产生尖峰,轻则导致ADC读数跳变,重则导致单片机复位。我一开始没注意这个问题,结果电机一启动,STM32就重启。
解决办法分三层:第一层是电源隔离,电机驱动和单片机用不同的稳压芯片,中间用磁珠或者电感隔离;第二层是滤波,电机两端并联0.1uF陶瓷电容,电源线上加LC滤波;第三层是软件滤波,ADC采集的时候避开电机启动瞬间,或者用中值滤波去掉突变值。
实测下来,这三层措施加上去之后,电机启动时ADC读数波动从±50LSB降到±5LSB以内,单片机也不再复位了。
5.4 船体平衡与防水密封检查
船体平衡问题我遇到过两次。第一次是电池放得太靠后,船头翘起来,螺旋桨半露出水面,推力不足。后来把电池移到船体中间,重心降低,问题解决。第二次是传感器探头装得太靠一侧,船体倾斜,转弯的时候容易翻。后来把探头对称布置,左右各一个,平衡问题解决。
防水密封检查是每次下水前必做的。我的流程是:先目视检查所有接缝和密封圈,看有没有裂纹或者老化;然后用打气筒往防水盒里打气,看有没有气泡漏出来;最后空载运行十分钟,看内部有没有水汽。这套流程走下来,基本能排除大部分防水隐患。
实操心得:亚克力胶水粘接的时候,一定要等24小时完全固化再下水。我有一次等了2小时就下水,结果接缝处渗水,电路板烧了一块。后来老老实实等24小时,再也没出过问题。
5.5 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| pH读数漂移 | ADC参考电压不稳 | 万用表测VDDA | 换低压差稳压芯片 |
| 浊度读数跳变 | 电机PWM干扰 | 示波器看ADC输入 | 加RC低通滤波 |
| 温度读数85°C | 单总线时序错误 | 检查上拉电阻 | 换4.7K上拉 |
| 通信中断 | 电源跌落 | 示波器看3.3V | 加大滤波电容 |
| 数据丢包 | WiFi信号弱 | 看RSSI值 | 加外置天线 |
| 电机启动复位 | 电源尖峰 | 示波器看5V | 加LC滤波 |
| 船体倾斜 | 重心偏移 | 目视检查 | 调整电池位置 |
| 防水盒进水 | 密封圈老化 | 打气测试 | 更换密封圈 |
6. 实测数据与性能评估
6.1 水质参数测量精度验证
为了验证测量精度,我拿这套系统和实验室台式水质分析仪做了对比。pH这边,在pH 4.00、6.86、9.18三个点,STM32系统读数分别是4.02、6.84、9.21,误差在±0.03pH以内。浊度这边,在0NTU、100NTU、500NTU、1000NTU四个点,STM32系统读数分别是3NTU、98NTU、510NTU、1020NTU,误差在±5%以内。温度这边,和标准温度计对比,误差在±0.2°C以内。
这个精度对于污水检测来说完全够用了。环保部门对水质监测的精度要求一般是pH±0.1、浊度±10%、温度±0.5°C,我们的系统都达标了。
6.2 续航与通信距离实测
续航测试是在静水中以50%速度连续航行,电池从满电放到保护板切断,总共跑了4小时20分钟。如果以100%速度跑,续航是2小时50分钟。这个成绩对于便携式设备来说算不错了,基本能满足半天的作业需求。
通信距离测试是在空旷水域,遥控器在岸边,船往远处开。NRF24L01在100米内信号稳定,超过100米开始丢包,150米完全失联。WiFi这边,ESP8266在50米内信号良好,超过50米丢包率上升,100米基本连不上。所以作业范围建议控制在50米以内,保证通信可靠。
6.3 不同水域环境适应性测试
我在三种水域做了测试:静水池塘、流动河道、有波浪的湖面。静水池塘表现最好,船体稳定,数据连续。流动河道有水流冲击,船体会有横向漂移,需要不断修正航向,但数据采集不受影响。有波浪的湖面最麻烦,船体上下颠簸,传感器探头偶尔露出水面,导致数据跳变。
针对波浪环境,我做了两个改进:一是把传感器探头往下延伸5cm,保证即使船体颠簸,探头也浸在水里;二是在软件里加了异常值剔除,如果连续三个采样值偏差超过50%,就判定为无效数据,不记录。改进之后,波浪环境下的数据可用率从70%提高到95%以上。
6.4 系统功耗分析与优化空间
功耗分析我用的是电流表加示波器,分别测了各个模块的电流。STM32在72MHz全速运行时约30mA,Stop模式约20uA。ESP8266在发送时约170mA,空闲时约15mA。电机在50%速度时约600mA,100%速度时约1.5A。传感器总共约20mA。
整体功耗在50%速度下约700mA,100%速度下约1.6A。优化空间主要在电机这边,如果换成无刷电机,效率能从60%提到85%,功耗能降30%左右。另外STM32可以进一步优化,把不用的外设时钟全部关掉,能再省几毫安。
7. 后续扩展方向与个人体会
7.1 功能扩展的几种可能路径
这套系统目前只测pH、浊度和温度三个参数,后续可以扩展溶解氧、电导率、氨氮等传感器。溶解氧传感器有荧光法和膜法两种,荧光法免维护但贵,膜法便宜但需要定期换膜。电导率传感器简单,两个电极加交流激励就行。氨氮传感器比较贵,离子选择电极法一套下来要上千,看预算决定。
通信这边可以升级到4G模块,实现远程数据传输。4G模块用EC20或者Air724,通过UART和STM32通信,AT指令集和ESP8266类似,迁移成本不高。上了4G之后,可以在云端做数据存储和分析,生成水质趋势图,更直观。
自主导航这边可以加视觉避障,用OpenMV或者K210跑简单的障碍物检测,遇到漂浮物自动绕开。还可以加自动采样功能,到了预设点位自动采集水样,带回实验室做更精确的分析。
7.2 我在这个项目里踩过的坑
第一个坑是ADC参考电压。一开始图省事,直接用3.3V做参考,结果电机一启动读数就飘。后来单独用REF3033做基准,问题解决。这个坑让我明白,模拟电路和数字电路一定要分开供电,参考电压一定要独立。
第二个坑是ESP8266供电。一开始和STM32共用AMS1117,结果一发数据就重启。后来单独用MP1584供电,问题解决。这个坑让我明白,无线模块的瞬态电流很大,电源一定要留足余量。
第三个坑是防水密封。第一次下水没等胶水完全固化,结果接缝渗水,烧了一块板子。后来老老实实等24小时,再也没出过问题。这个坑让我明白,防水这件事急不得,该等的时间一定要等。
7.3 给后来者的几点实用建议
如果你也想做类似的污水检测船,我的建议是:先从最小系统开始,把STM32和传感器跑通,再逐步加通信和动力。不要一上来就全部搭好,出了问题不好定位。
传感器校准一定要做,而且要用标准液做,不要凭感觉。校准数据存在STM32的Flash里,掉电不丢。每次更换传感器或者长时间不用之后,都要重新校准。
电源设计要留余量,电机和通信模块的瞬态电流都很大,稳压芯片的额定电流至少要是实际电流的两倍。滤波电容要多加,电解电容和陶瓷电容搭配使用,效果更好。
防水处理要细致,所有接缝都要涂胶,所有出线孔都要用防水接头。下水前一定要做打气测试,确认没有漏气的地方。
最后,调试的时候要有耐心。嵌入式系统的问题往往不是单一原因,而是多个因素叠加。遇到问题不要慌,用示波器、万用表一步步排查,总能找到原因。我调试这套系统花了将近一个月,中间无数次想放弃,但每次解决问题之后的成就感,让我觉得一切都值得。