基于STM32的鱼缸水质检测系统

水温+浑浊度+pH三参数监测、超标自动换水、手机APP远程查看,附"摘要吹溶氧氨氮、图注抄成GPS"翻车实录

养鱼先养水。鱼缸水质崩了,鱼翻肚往往就在一夜之间------等你肉眼发现水浑、鱼浮头,亚硝酸盐早就爆表了。市面上一支带温度补偿的 pH 笔就要上百,溶氧仪更是几百起步。其实用 STM32 + 三支传感器,一百出头就能做一套水温、浑浊度、pH 三参数实时监测 + 超标报警 + 自动换水 + 手机远程查看的系统。

一、系统功能拆解

功能域 模块 说明
水质监测 DS18B20 防水探头 水温检测,超阈值报警
水质监测 SEN0189 红外浑浊度 水中颗粒物散射测浑浊,超阈值报警
水质监测 PH-4502C + pH 电极 酸碱度检测,超标触发换水泵
人机交互 OLED12864 实时显示三参数
人机交互 4 按键 本地设置阈值
远程通信 ESP8266(MQTT→阿里云) 数据上云,APP 远程查看+设阈值
报警执行 蜂鸣器 + LED 超限声光报警
换水执行 继电器 + 小水泵 pH 超标自动换水(带防抽干保护)

主逻辑:初始化 → 循环采集三参数 → OLED 刷新 → MQTT 上云 → 水温/浑浊度超阈值声光报警 → pH 超标启动换水泵(限时保护)→ 响应按键与 APP 指令。

二、器件选型对比

2.1 主控:STM32F103C8T6 vs STM32F407VG

三路采集里两路是 ADC(浑浊度、pH),C8T6 自带 2 个 12 位 ADC、10 个通道完全够用,选它合理。

2.2 水温:DS18B20 vs LM35

DS18B20 提供了更高的测量精度和更广泛的温度范围------LM35 精度 ±0.25°C 高于 DS18B20 的 ±0.5°C,量程 150°C 也宽于 125°C。DS18B20 真正的优势是防水封装成品探头 + 数字输出免标定,鱼缸场景就该选它,但理由得写对。

2.3 浑浊度:SEN0189 红外 vs SEN0176 激光

对比项 SEN0189(红外 850nm) SEN0176(激光)
原理 红外 LED + 光电管测散射 激光散射,分辨率高
价格 ≈45 元 ≈200+ 元
适用 家用浑浊度粗判 精密测量

家用鱼缸只需要知道"水是否开始浑了",SEN0189 够用。注意:SEN0189 输出的是模拟电压,"浑浊度百分比"并没有严格的物理单位,正规写法应换算 NTU 或直接以电压/ADC 值表征

2.4 pH:PH-4502C vs SEN0161

PH-4502C(±0.1pH,配 BNC 电极)比 SEN0161(±0.2pH)精度高一档,做水质监测选它合理。

2.5 通信与显示

ESP8266-01S(家庭 Wi-Fi 直连)+ OLED12864(I2C),常规选择。

2.6 BOM 成本清单

器件 参考价
STM32F103C8T6 最小系统板 ≈15 元
DS18B20 防水探头 ≈8 元
SEN0189 浑浊度模块 ≈45 元
PH-4502C + pH 玻璃电极 ≈30 元
ESP8266-01S ≈10 元
OLED12864(I2C) ≈10 元
继电器 + 5V 小水泵 ≈15 元
蜂鸣器、LED、按键、洞洞板 ≈10 元
合计 ≈143 元

三、硬件接线

模块 引脚 说明
DS18B20 DQ PB8 4.7kΩ 上拉,防水探头直接入水
SEN0189 AO PA1(ADC1_IN1) 5V 供电,AO 输出注意量程
PH-4502C OUT PB1(ADC1_IN9)→ 分压后 ⚠️ 见接线坑 1
OLED SDA/SCL PB6/PB7(I2C1) ---
ESP8266 TX/RX PA2/PA3(USART2) 115200bps
继电器(水泵) PA0 高电平吸合
蜂鸣器 PB9 高电平响
按键×4 PB12~PB15 内部上拉

接线坑三条

  1. PH-4502C 的 5V/3.3V 混搭问题 :板子 5V 供电,OUT 静态输出约 2.5V、极限可到 5V,直接接 F103 的 ADC 有过压风险(F103 引脚耐压 3.6V,ADC 满量程 3.3V)。用两个 10kΩ 分压成 0~2.5V 再进 ADC,标定时把分压比一起标进去。
  2. 两个 ADC 别用 ADC3 :原文 pH 章节调用 Get_Adc3------C8T6 根本没有 ADC3(ADC3 只在 100 脚以上的 F103 才有),浑浊度章节又用 ADC2。实际两路都挂 ADC1 的不同通道即可,代码抄大的芯片的工程就会出这种错。
  3. 水泵走继电器隔离:5V 潜水泵启动电流是标称的 3~5 倍,别用 IO 直推;继电器线圈两端并一个续流二极管(1N4007),否则断电瞬间反向电动势会打坏驱动管。

四、软件设计

4.1 主程序框架

复制代码
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    delay_init();
    TIM4_Init(300, 7200);            /* 1ms 时基 */
    OLED_Init();
    DS18B20_Init();                  /* PB8 水温 */
    Relay_init();                    /* PA0 换水泵 */
    KEY_Init();                      /* PB12~PB15 */
    Beep_init();                     /* PB9 */
    Adc_Init();                      /* PA1 浑浊度 / PB1 pH */
    ALi_ESP8266_GPIO_Init();
    MQTT_Buff_Init();
    AliIoT_Parameter_Init();

    while (1)
    {
        Sensor_Update();             /* 三参数采集 */
        OLED_Display_Cotrol();       /* 显示刷新 */
        Alarm_Check();               /* 水温/浑浊度超限 -> 声光报警 */
        PH_AutoWater();              /* pH 超标 -> 换水(限时保护) */
        Key_Scan();                  /* 阈值设置 */
        MQTT_Loop();                 /* 上报 + 响应 APP 指令 */
    }
}

4.2 关键子程序一:DS18B20 非阻塞读水温

复制代码
void DS18B20_Task(void)
{
    static u8 phase = 0;
    static u32 t0;

    switch (phase) {
    case 0:                          /* 发起转换 */
        DS18B20_Reset();
        DS18B20_WriteByte(0xCC);     /* 跳过ROM */
        DS18B20_WriteByte(0x44);     /* 启动转换 */
        t0 = GetTick();
        phase = 1;
        break;
    case 1:                          /* 750ms 后再读,期间不阻塞主循环 */
        if (GetTick() - t0 >= 750) {
            DS18B20_Reset();
            DS18B20_WriteByte(0xCC);
            DS18B20_WriteByte(0xBE); /* 读暂存器 */
            u8 tl = DS18B20_ReadByte();
            u8 th = DS18B20_ReadByte();
            water_temp = ((s16)((th << 8) | tl)) * 0.0625f;
            phase = 0;
        }
        break;
    }
}

4.3 关键子程序二:pH 两点校准(原文完全没做的一步)

pH 电极的能斯特响应是一条直线 pH = K * V + B,K 和 B 由两种标准液标定:

复制代码
typedef struct { float v4, v7; } PH_Calib;   /* 标定电压 */

float PH_GetValue(PH_Calib *c)
{
    float v = Adc_ReadAvg(CH_PH, 20) * 3.3f / 4095;  /* 分压后电压 */
    /* 两点法:pH4.01 对应 v4,pH6.86 对应 v7 */
    float k = (4.01f - 6.86f) / (c->v4 - c->v7);
    float ph = 6.86f + k * (v - c->v7);
    /* 温度补偿:水温每偏离 25°C,斜率约变化 0.3%/°C */
    ph -= (ph - 7.0f) * (water_temp - 25.0f) * 0.003f;
    return ph;
}

标定流程:电极依次插入 pH6.86 和 pH4.01 标液,各按一次"校准键"记录电压,存 Flash。电极每 1~2 个月要重校,玻璃电极干放后要先浸泡活化。

4.4 关键子程序三:SEN0189 浑浊度采样

复制代码
u16 Turbidity_GetAdc(void)
{
    u32 sum = 0;
    u8 i;
    for (i = 0; i < 20; i++) {
        sum += Get_Adc(CH_TURB);
        delay_ms(2);
    }
    return (u16)(sum / 20);          /* 均值滤波 */
}

表述建议:显示"浑浊度 ADC 值/电压"并标注"数值越大水越浑"即可;硬要 NTU 需要专业浊度仪对比标定。

4.5 关键子程序四:pH 超标自动换水(带防抽干保护)

复制代码
#define PUMP_MAX_RUN_MS  60000   /* 单次最多抽 60s(按缸容积算好) */
#define PH_HYST           0.5f   /* 回差,防止在阈值附近反复启停 */

void PH_AutoWater(void)
{
    static u32 t_start;
    static u8 running = 0;
    float ph = PH_GetValue(&ph_calib);

    if (!running) {
        if (ph > ph_high_th + PH_HYST || ph < ph_low_th - PH_HYST) {
            running = 1;
            t_start = GetTick();
            Relay_On();                       /* 开泵抽旧水 */
        }
    } else {
        if (GetTick() - t_start >= PUMP_MAX_RUN_MS) {
            Relay_Off();                      /* 限时到,强制停 */
            running = 0;
            Beep_On();                        /* 提醒用户手动补新水 */
        }
    }
}

想做成真"自动换水":加水位传感器(或双泵 + 蓄水桶),按"抽 20% → 补 20%"流程闭环;pH 偏酸用小苏打、偏碱用榄仁叶纠正------换水本身只是稀释,不能定向调 pH。

五、系统调试验证

测试项 方法 预期结果
水温 与温度计对比 误差 ±0.5°C 内
浑浊度 清水 vs 投饵后水样 ADC 值明显区分,阈值可调
pH 校准 6.86/4.01 标液两点标定 标液回测误差 ≤±0.1pH
pH 精度 测 pH5/7/9 缓冲液 误差 ≤±0.2pH
报警 人为调低阈值触发 蜂鸣+LED,APP 收到推送
自动换水 pH 超上限 泵启动 60s 后自动停止并提示
通信 关 Wi-Fi 30s 再开 自动重连,数据续传

六、可扩展方向

  • 补氨氮/亚硝酸盐:虽然低成本离子选择性电极精度一般,但可以做趋势预警;比摘要空吹强;
  • 真·自动换水:双泵 + 蓄水桶 + 水位/霍尔传感器,抽补联动闭环;
  • 加热棒联动:水温低于设定自动开加热棒(继电器+防水加热棒),养热带鱼刚需;
  • 喂食提醒:RTC 定时 + APP 推送,把系统升级为完整"智能鱼缸管家"。

八、资料内容完整工程资料(原理图、PCB、代码、元件清单)

九、资料获取方式

相关推荐
HRTOS1 小时前
HRTOS 4.0 正式发布:Driver Library 基础外设驱动模块介绍
驱动开发·单片机·嵌入式硬件·51单片机
染予2 小时前
20个点位下发该如何正常操作?
单片机·嵌入式硬件
wuyk5552 小时前
从零吃透 MQTT 通信|第 5 章 MQTT 心跳保活机制深度优化,断线检测与智能自动重连
c语言·开发语言·stm32·学习
jianqiang.xue3 小时前
ESP-IDF保姆级入门23|MQTT物联网通信全解:发布订阅模式/QoS等级/遗嘱消息/主题设计/断线重连,掌握工业级标准消息通信
stm32·单片机·mcu·物联网·51单片机·iot
HRTOS3 小时前
HRTOS 4.0 Driver Library:03_Sensor 传感器驱动
驱动开发·单片机·嵌入式硬件·51单片机
youcans_3 小时前
【嵌入式软件AI编程】01. 基于 STM32/Claude Code的AI编程
stm32·mcu·嵌入式·ai编程·claude code
小麦嵌入式3 小时前
FPGA入门(十一):受控线性序列机 UART 发送升级
stm32·单片机·嵌入式硬件·mcu·fpga开发·硬件工程
jianqiang.xue4 小时前
ESP-IDF保姆级入门29|FreeRTOS任务管理与调度全解:任务创建/状态切换/优先级调度/双核负载均衡/实时性优化,掌握嵌入式多任务编程核心
stm32·单片机·mcu·物联网·51单片机·iot
自小吃多4 小时前
PCB Editor软件走线、修线操作笔记
笔记·嵌入式硬件