简介:一套基于STM32的海水盐度检测系统完整工程,配套LabVIEW上位机软件,适合单片机开发者及海洋监测相关课程设计、毕业设计参考。系统下位机采用STM32F1与uC/OS-II,实现浑浊度传感器AD采集、DS18B20防水温度测量、OLED(SPI七线)实时显示,并通过ESP8266组建WiFi服务端,按问答式通信协议向上位机发送温度、盐度及温补后盐度、补偿百分比;包内附带盐度算法公式与系数补偿资料,函数接口清晰,便于移植或二次开发。资源共1071个文件,约24.3MB,以嵌入式c/h源码、Keil/UV工程、PDF说明文档及LabVIEW工程文件为主,同时包含hex、map、调试记录等辅助文件,目录结构完整,可对照学习。已有1426人学习下载,适合希望快速搭建海水盐度监测原型并掌握STM32+ESP8266+LabVIEW整套通信链路的开发者。 使用STM32和LabVIEW做了一套海水盐度检测系统,今天把整个从硬件选型、下位机程序、上位机界面到联调的过程完整拆解一遍。文中会涉及很多实操细节和踩坑记录,希望能给正在做同类项目,或者准备用STM32配合LabVIEW做数据采集系统的同学一些参考。
1. 系统整体方案与设计思路
这套海水盐度检测系统的核心任务是:通过电导率传感器采集海水样本的电导率数据,结合温度补偿算法换算成盐度值,在本地LCD屏上实时显示,同时通过串口将数据发送给PC端的LabVIEW上位机,实现远程监控、波形显示和数据记录。
听到“海水盐度检测”,很多人第一反应是去买现成的盐度计模块,比如工业用的电导率变送器。这类模块确实省事,输出标准的4-20mA或RS485信号,但价格偏高,而且作为学习或DIY项目来说,少了底层信号处理的乐趣。更关键的是,如果未来你想拓展测量范围、改进算法或降低成本,固化模块基本没有二次开发空间。
所以我没有用一体化变送器,而是采用传感器探头 + 信号调理电路 + STM32处理的方案。整套系统构成为:
- 电导率探头:两个石墨电极的电极式探头,电极常数K约为1.0
- 信号调理电路:交流激励源、I/V变换、精密整流、滤波放大
- 主控:STM32F103C8T6,完成ADC采样、温度读取、盐度算法、LCD显示、串口发送
- 温度传感器:DS18B20,用于温度补偿
- 人机交互:0.96寸OLED屏(调试阶段用)或1602LCD(成品阶段)
- 上位机:LabVIEW + VISA串口通信 + UI界面 + 数据存储
下位机负责采集和计算,上位机负责显示和记录,中间通过USB转TTL串口连接,通信协议是自己定义的Modbus-RTU简化版。
这里补充一下为什么用STM32F103C8T6。这块芯片虽然是几年前的“老将”了,但胜在性价比极高、资料极多、库函数成熟,做这种信号采集和协议转换的活儿绰绰有余。更重要的是,绝大多数人电脑里已经备好了它的开发环境,不用额外折腾。如果你想直接用STM32F407或H743也完全可以,程序逻辑基本一致,就是ADC和时钟配置略有差别,后面我会提到。
2. 盐度检测原理与信号调理电路设计
2.1 为什么用电导率法测盐度
海水盐度的检测方法主要有:重量法(烘干称重)、银量滴定法(化学分析)、折射率法(光学)、电导率法(物理电学)。前两种精度高但只能离线检测,无法实时在线;折射率法设备昂贵;电导率法因为海水中盐分主要以离子形式存在,离子浓度越高导电能力越强,电导率和盐度之间存在稳定的对应关系,所以成为目前在线盐度检测最主流的手段。
用电导率换算盐度,本质上是在测量溶液电阻。两片电极插入溶液中,溶液相当于一个电阻,阻值范围根据盐度不同可能从几十欧到几千欧变化。只要测出这个电阻值,再结合温度修正和经验公式,就能换算出盐度。
但这里有个关键问题:直流电通过溶液会发生电解,电极表面产生极化,导致测量极不稳定。所以绝对不能直接用直流去测溶液电阻,必须用交流激励信号。
2.2 信号调理电路具体方案
借鉴常见工业电导率仪的设计思路,我设计了一版简化的信号调理电路,整体分为五级:
激励源:用STM32的TIM定时器输出一个频率1kHz、占空比50%的方波,经RC低通滤波整形成正弦波,再通过电压跟随器驱动电极。方波本身含直流分量,必须隔直后再送入电极。
I/V变换:电极回路串联一个精密采样电阻(10Ω),通过运放将流过电极的电流信号转换为电压信号。这个环节的核心是运放输入偏置电流要小,推荐使用OP07或OPA2277这类低失调运放。
隔直与精密整流:因为激励是交流信号,采样电压也是交流,需要先隔直再整流成直流方便ADC采样。用两个二极管加运放组成的半波精密整流电路,能把毫伏级的交流信号线性整流为直流。
滤波放大:整流后的信号含有大量纹波,用二阶低通滤波器平滑处理,截止频率设为100Hz左右。
ADC采样:STM32的ADC1通道0采集滤波输出,通过DMA方式连续读取32次取平均,减小干扰。
这套电路的优点是:元器件很普通,成本十来块钱搞定;调试时可以用示波器逐级观察信号波形,方便定位问题。缺点是电路板布局和噪声抑制容易踩坑,后面第5部分会重点讲。
2.3 盐度换算公式与温度补偿
电导率受温度影响很大,实测数据表明,温度每升高1℃,电导率大约增加2%左右。如果不对温度做补偿,夏天和冬天测同一杯海水,读数会差一大截。
盐度换算采用国际上常用的经验公式,简化处理后如下:
S = a0 + a1 * (Gt / G25) + a2 * (Gt / G25)^2 + a3 * (Gt / G25)^3
其中Gt为当前温度下测得的电导率,G25为25℃时的标准电导率,系数a0、a1、a2、a3是通过标准海水标定得到的常数。实际代码里,为了简化计算,我采用了更直观的方法:先在实验室配制多组已知盐度的标准溶液,用系统实测电导率,再用最小二乘法拟合成一条“电导率-盐度”曲线,标定系数存入Flash。
温度补偿使用线性补偿模型:
G25 = Gt / (1 + 0.02 * (T - 25))
这个模型虽然比不过国际标准实用盐度公式(PSS-78)的精度,但用在教学演示和一般水产养殖监测场景完全够用。如果追求更高精度,可以引入PSS-78公式的查表法实现,不过对MCU的存储和算力要求会高一些。
3. STM32下位机程序设计要点
3.1 工程创建与资源分配
我使用的是STM32标准外设库(V3.5版本),开发环境为Keil MDK5。工程结构划分为:系统时钟、GPIO初始化、TIM定时器、ADC采集、DS18B20驱动、串口通信、盐度算法、主循环。
因为F103C8T6只有一个ADC模块,但采样通道多,我用的是ADC1的通道0,配置为连续转换模式,配合DMA1通道1自动搬运数据,避免CPU反复进出中断。DMA缓冲数组设为64位,每满64次触发一次传输完成中断,取平均后作为一次有效电导率值。
需要注意的一个细节是:ADC的采样时间必须和激励信号频率搭配。激励源是1kHz,整流滤波后输出基本是一路平滑直流,但仍有残余纹波。如果采样时间太短,采到的点可能落在纹波的不同相位上,导致读数抖动。实测下来,ADC采样周期对最终读数平滑度影响很大,我最终将ADC采样时间设为239.5个周期,配合DMA平均后效果已很理想。
3.2 串口通信协议设计
下位机每隔500ms主动向上位机发送一帧数据。帧格式定义如下:
帧头(0xAA) | 功能码(0x01) | 数据长度(0x06) | 盐度高字节 | 盐度低字节 | 温度高字节 | 温度低字节 | 校验和盐度和温度都放大10倍后以整数形式传输,比如盐度25.3‰传输为253,接收端再除以10。这样做的好处是避免浮点数在串口传输中的字节序问题,也方便上位机解析。
校验和采用最简单的8位累加和校验:从帧头到最后一个数据字节累加取低8位。虽然简单,但对于这个数据量很小的场景,误码率可以忽略。如果未来要传输更复杂的数据,建议换成CRC16。
3.3 上位机协议响应的处理
我在下位机里多加了一个功能:收到上位机的0x02命令时,回传当前系统状态,包括固件版本、最近一次校准时间、ADC原始值等。这种设计在调试联调阶段非常实用,可以直接通过上位机按钮查询下位机状态,不必重新插拔USB线看串口助手。
4. LabVIEW上位机开发与实现
4.1 串口通信模块搭建
LabVIEW与STM32通信最常用的方式就是VISA,它屏蔽了底层驱动的复杂性,拿串口数据就像读文件一样方便。基本流程是:
- VISA Configure Serial Port:配置串口号、波特率(115200)、数据位(8)、停止位(1)、无校验
- VISA Read:按预设字节数读取数据
- 解析帧数据:查找帧头、校验数据、拆分盐度和温度字节
- VISA Close:程序退出前释放串口资源
这里有个容易忽略的地方:VISA Read的字节数要设置成“请求读取的字节数”还是“实际存在的字节数”?如果请求字节数大于实际到达的字节数,VISA会一直等待,直到超时时间(Timeout)到,程序界面就卡住了。我最初就踩了这个坑,界面每隔几秒假死一次,后来改成“VISA Bytes at Serial Port”属性节点先查询缓冲区实际字节数,再按实际字节去读,问题就消失了。
4.2 数据可视化与存储
上位机界面分为三个区域:
- 仪表盘区域:一个圆形仪表显示实时盐度值,一个温度计显示实时温度
- 波形图区域:盐度和温度的历史趋势图,横轴为时间,纵轴为盐度值/温度值
- 状态栏区域:串口连接状态、数据帧计数、当前时间
盐度变化是缓慢过程,波形图的显示缓冲区设为2000个点,超过后自动滚动覆盖。做这一块时,不要在主循环里使用“等待(ms)”函数,而是要使用“等待下一个整数倍毫秒”,保证波形图的时间轴均匀推进。
数据存储用了“写入测量文件”Express VI,它会自动生成带表头的Excel或TDMS文件,每一行对应一次采样时间、盐度值、温度值。TDMS文件是NI的专有格式,写入速度快,但别人没有LabVIEW环境就打不开;Excel通用性好,但写入频繁时文件会变大变慢。我给这个项目做成了可配置的:默认存TDMS,勾选“同时导出Excel”时额外写一份Excel。
4.3 扩展:Modbus RTU与多设备管理
做这套系统的时候,我还顺便把Modbus RTU模式也加进去了。下位机作为Modbus从站,地址为1,上位机用LabVIEW的Modbus库做主站。
这个功能的价值在于:如果以后要多点监测(比如不同水深的盐度变化),只需给每台设备分配不同地址,上位机就能轮询采集多台数据,不用重新改通信协议。LabVIEW的Modbus库是NI官方免费提供的,安装后直接从函数面板拖出来就能用,不需要额外花钱。
5. 常见问题与排查技巧实录
5.1 ADC采样值跳动特别大
现象:屏幕上盐度读数乱跳,波动范围超过5‰,远超正常水平。
排查过程:首先用万用表测量信号调理电路各级输出电压,发现整流滤波输出端电压波动不大,问题应该出在ADC采集环节。接着用示波器看STM32的参考电压引脚(VREF+),发现上面叠加了100mV左右的周期波动——这是板载3.3V稳压芯片输出纹波过大导致的。
解决方法:
- 在VREF+引脚和地之间并联一个10uF钽电容和0.1uF瓷片电容
- ADC采样时间调大,增加数字滤波
- 软件上采用滑动平均滤波,窗口设为16
经过这三步处理后,ADC原始值的峰峰值从约45个LSB降到了4个LSB以内,换算成盐度误差只有0.1‰左右。
5.2 串口连接不上或数据传输乱码
这个问题一半以上的同学都会遇到。常见原因有三个:
- 串口号不对。USB转TTL模块在老系统上可能分配的不是COM1~COM4,而是COM10以后,LabVIEW老版本的VISA可能识别不到,建议在设备管理器里手动改一个靠前的COM号。
- 波特率不一致。下位机和上位机任何一个地方设错就无法通信。
- 接了CH340的USB转TTL模块,但TTL电平的TXD/RXD没有交叉连接。下位机的TXD接USB模块的RXD,下位机的RXD接USB模块的TXD,很多新手习惯性地“直通”,结果数据全乱。
另外一个很隐蔽的问题:STM32如果用的是5V供电,串口电平可能不是标准3.3V,个别USB转TTL模块可能识别异常。保险起见,STM32板子用3.3V供电,USB模块的VCC只用来供它自己。
5.3 调试时常见“Error: No STM32 Target Found”
这是用ST-Link下载程序时最经典的报错。多数情况是ST-Link和目标板之间的接线问题,排查顺序:
- 确认SWDIO和SWCLK两根信号线没有接反,GND必须共地
- 确认目标板供电正常且电压在规定范围
- 在Keil的Options for Target里重新选择ST-Link Debugger,并点击Settings查看是否能扫描到目标芯片IDCODE
- 如果之前程序把SWD引脚复用为普通GPIO,需要先按住目标板复位键再点击下载,并在下载瞬间释放复位
最后一种情况的原理是:程序启动后马上把SWD引脚改成了普通GPIO,调试器就失去控制能力了。按住复位键时内核暂停在复位状态,调试器趁这个间隙尝试连接,所以能成功。
5.4 LabVIEW安装与运行常见坑
LabVIEW 2018之后的安装包都比较大(4GB以上),安装路径不要带中文或空格,否则某些NI驱动可能找不到文件。装好后先在NI MAX里测试能否识别USB转串口设备,如果NI MAX里看不到对应设备,LabVIEW的VISA自然也无法使用。
如果遇到“VISA驱动未安装”的错误,去NI官网单独下载NI-VISA最新版安装包重装即可,不需要重装LabVIEW。
5.5 盐度读数和实际差距大
这种情况十有八九是没做标定或者标定系数不对。电导率测量是相对测量,必须用标准溶液标定才能准。我用的是购买的25.0‰标准海水盐度校准液,在25℃恒温条件下进行一点标定,标定好的偏置系数存Flash。
需要注意,不同批次电极的极板面积、距离有差异,电极常数会不同,换新探头后必须重新标定。如果条件有限,可以用海盐人工配制近似浓度的盐水,再用比重计或折射式盐度计做参考,配出接近25‰的溶液后再标定。精度虽然没有标准液高,但用于日常监测和教学演示足够了。
我还做过多点标定:用5‰、15‰、25‰、35‰四组标准液分别测电导率,然后做二次多项式拟合。实测下来,在5‰~35‰范围内,单点标定的均方根误差是1.05‰,多点标定可以把误差压到0.3‰以内。如果项目对精度要求较高,建议做多点标定。
6. 扩展思考
这套系统目前的通信方式是有线串口,还可以做两个方向的升级:
- 加一个ESP8266或ESP32,将串口数据转为WiFi信号,上位机端改用TCP/IP通信,实现无线监测。LabVIEW的TCP/IP节点用法和VISA类似,学习成本不高。
- 加一个4G模块DTU,数据上云,小程序或网页端远程查看,适合水产养殖基地这种多点多地部署场景。
硬件端也可以考虑把电导率探头换成四电极结构,能大幅度降低电极极化和海生物附着的影响,是工业级产品的标准方案,精度和稳定性比两电极高不少。
我个人实际做完这套系统最大的体会是:测盐度这个任务本身难度不算特别高,难点全在信号链路的稳定性和标定的精细程度上。很多同学做完下位机就觉得万事大吉,等到联调时才发现一堆模拟电路和通信匹配的问题。建议在做的时候,先把信号调理电路单独搭出来,用示波器确认每一级输出都在预期范围内,再写软件。模数混合系统里,硬件不稳,软件写得再好也是白搭。
本文还有配套的精品资源,点击获取