基于STM32设计的智能游泳池水质监测系统
项目开发背景
游泳池作为公共休闲和健身场所,其水质安全直接关系到使用者的健康与舒适。水质参数如pH值、余氯浓度和浊度是衡量水质的关键指标,若控制不当,可能导致细菌滋生、皮肤刺激或其他健康风险,因此对游泳池水质进行持续、准确的监测至关重要。
传统的游泳池水质管理多依赖人工定期检测和手动调节,这种方式效率低下且容易因人为误差或延迟响应导致水质波动。尤其在高峰期或大型泳池中,实时监控和快速调整变得困难,增加了运营成本和安全隐患,亟需引入自动化、智能化的解决方案。
随着物联网和嵌入式技术的快速发展,基于微控制器的智能监测系统成为提升水质管理效率的有效途径。本系统采用STM32F103C8T6作为核心控制器,结合高精度传感器和Wi-Fi通信模块,能够实时采集和分析水质数据,并通过自动控制机制调节相关设备,同时利用云平台和上位机实现远程监控与数据记录,为游泳池运营提供可靠的技术支持。
该项目的开发旨在构建一套高效、低功耗的智能水质监测系统,通过实时预警和趋势分析,帮助管理人员及时应对水质异常,降低维护成本,并提升用户体验,为现代游泳池的智能化管理提供实用参考。
设计实现的功能
(1)实时监测游泳池水pH值、余氯浓度和浊度
(2)自动控制水质调节设备运行
(3)水质数据异常预警和记录
(4)QT上位机显示水质参数变化趋势和设备状态
项目硬件模块组成
(1)STM32F103C8T6最小系统核心板作为主控制器
(2)PH-4502C pH传感器监测酸碱度
(3)余氯传感器模块监测氯含量
(4)浊度传感器监测水质清澈度
(5)ESP8266-01S Wi-Fi模块连接华为云平台
(6)洞洞板焊接传感器接口电路,杜邦线连接各模块
设计意义
该智能游泳池水质监测系统的设计意义在于实现对游泳池水质的实时、精确监测,通过集成pH值、余氯浓度和浊度传感器,系统能够持续采集关键水质参数,确保水质始终处于安全范围内。这种自动化监测减少了人工检测的频率和误差,提高了监控的可靠性和效率。
系统通过自动控制水质调节设备运行,能够在检测到参数异常时及时调整,如添加消毒剂或调节酸碱度,从而保障游泳者的健康与安全。避免因水质问题导致的皮肤刺激、眼部不适或更严重的健康风险,提升游泳池的使用体验和卫生标准。
水质数据异常预警和记录功能使得管理人员能够快速响应潜在问题,历史数据记录有助于分析水质变化趋势,为长期维护和优化提供数据支持。这降低了运营成本,延长了设备寿命,并确保了合规性。
通过ESP8266 Wi-Fi模块连接华为云平台和QT上位机显示,实现了远程监控和数据可视化,管理人员可以随时随地查看水质参数变化趋势和设备状态,便于及时决策和干预,增强了系统的智能化和便捷性。
设计思路
该系统以STM32F103C8T6微控制器为核心,负责协调整个监测系统的运行。通过其内置的ADC模块实时采集pH传感器、余氯传感器和浊度传感器的模拟信号,并将这些数据转换为数字值进行处理。STM32还负责控制水质调节设备的开关,例如根据监测结果自动启动加氯泵或pH调节剂投放装置,以维持水质参数在预设的安全范围内。
传感器数据采集部分使用PH-4502C pH传感器监测水的酸碱度,余氯传感器模块检测氯离子浓度,浊度传感器评估水的清澈程度。这些传感器通过洞洞板焊接的接口电路连接到STM32的相应引脚,使用杜邦线进行物理连接,确保信号稳定传输和简化硬件布局。
数据处理与异常预警功能由STM32实时执行,它将采集到的pH值、余氯浓度和浊度数据与预设阈值进行比较。如果任何参数超出正常范围,系统会立即触发预警机制,例如通过内部标志或连接的外设发出警报,同时将异常事件记录到STM32的存储器中,便于后续分析和追溯。
自动控制机制基于监测数据动态调整水质调节设备。例如,当余氯浓度低于设定值时,STM32会输出控制信号启动加氯设备;当pH值偏离理想范围时,则调节酸碱度投放装置的运行。这种闭环控制逻辑通过STM32的GPIO和定时器功能实现,确保水质持续保持在健康水平。
通信部分通过ESP8266-01S Wi-Fi模块将STM32连接到华为云平台,实现数据的远程传输和存储。水质参数、设备状态及异常记录定期上传至云平台,用户可以通过网络实时监控系统运行情况,并利用云服务进行数据备份和远程管理。
QT上位机应用程序作为人机交互界面,从云平台或直接通过通信接口接收数据,以图形化方式显示水质参数的历史变化趋势和设备当前状态。这提供了直观的监控体验,帮助用户快速识别水质问题并做出相应决策。
硬件组装方面,所有模块包括STM32核心板、传感器和Wi-Fi模块均在洞洞板上进行焊接和固定,传感器接口电路设计考虑了信号匹配和抗干扰能力。杜邦线用于灵活连接各组件,简化了系统的布线和维护过程,确保整体结构的可靠性和易扩展性。
框架图
+-------------------------+
| 传感器层 |
| +----------+----------+ |
| | pH传感器 | 余氯传感器| |
| +----------+----------+ |
| +----------+ |
| | 浊度传感器| |
| +----------+ |
+-------------------------+
|
v
+-------------------------+
| 控制层 |
| +---------------------+ |
| | STM32F103C8T6 | |
| | 主控制器 | |
| | - 数据采集 | |
| | - 数据处理 | |
| | - 控制逻辑 | |
| +---------------------+ |
+-------------------------+
|
|-----------------> +-------------------------+
| | 执行层 |
| | +---------------------+ |
| | | 水质调节设备 | |
| | | (加氯机、pH调节等) | |
| | +---------------------+ |
| +-------------------------+
|
v
+-------------------------+
| 通信层 |
| +---------------------+ |
| | ESP8266 Wi-Fi模块 | |
| | 连接华为云平台 | |
| +---------------------+ |
+-------------------------+
|
v
+-------------------------+
| 云平台层 |
| +---------------------+ |
| | 华为云 | |
| | - 数据存储 | |
| | - 异常预警 | |
| | - 记录日志 | |
| +---------------------+ |
+-------------------------+
|
v
+-------------------------+
| 应用层 |
| +---------------------+ |
| | QT上位机 | |
| | - 显示水质参数 | |
| | - 显示趋势 | |
| | - 设备状态 | |
| +---------------------+ |
+-------------------------+
系统总体设计
本系统以STM32F103C8T6最小系统核心板作为主控制器,负责整体协调和数据处理。该系统通过集成PH-4502C pH传感器、余氯传感器模块和浊度传感器,实时采集游泳池水的关键参数,包括酸碱度、氯含量和清澈度。这些传感器通过洞洞板焊接的接口电路和杜邦线连接到主控制器,确保稳定可靠的数据传输。
系统通过STM32主控制器对采集的传感器数据进行实时分析和处理,并根据预设阈值自动控制水质调节设备的运行。例如,当pH值或余氯浓度超出正常范围时,控制器会触发相应设备进行调节,以维持水质的平衡状态。同时,系统具备数据异常预警功能,能够及时检测到水质参数异常并记录相关事件,便于后续查询和分析。
为了远程监控和数据存储,系统集成了ESP8266-01S Wi-Fi模块,该模块将处理后的水质数据上传至华为云平台。通过云平台,用户可以实时访问水质信息,并实现历史数据的备份和查询。此外,系统还支持QT上位机显示界面,该界面直观展示水质参数的变化趋势和设备运行状态,帮助用户全面了解游泳池水质的动态情况。
整个设计注重实用性和可靠性,通过硬件组件的合理布局和软件算法的优化,确保系统能够长期稳定运行。自动控制机制和预警功能进一步提升了系统的智能化水平,有效保障游泳池水质的卫生与安全。
系统功能总结
| 功能 | 描述 |
|---|---|
| 实时监测水质参数 | 使用pH传感器、余氯传感器和浊度传感器,实时监测游泳池水的pH值、余氯浓度和浊度 |
| 自动控制水质调节设备 | 基于监测数据,自动控制水质调节设备的运行,以维持水质标准 |
| 水质数据异常预警和记录 | 当水质参数异常时,系统发出预警,并记录异常数据用于后续分析 |
| QT上位机显示 | 通过Wi-Fi模块连接云平台,在QT开发的上位机上显示水质参数变化趋势和设备状态 |
设计的各个功能模块描述
STM32F103C8T6最小系统核心板作为主控制器,负责协调整个系统的运行,包括采集传感器数据、处理水质参数、执行自动控制逻辑、管理通信连接以及实现预警和记录功能。它通过内置的ADC和GPIO接口与各模块交互,确保实时性和稳定性。
PH-4502C pH传感器模块用于监测游泳池水的酸碱度,其输出模拟信号经过STM32的ADC转换后得到pH值数据。该模块通过洞洞板焊接的接口电路与主控制器连接,确保信号传输的准确性和抗干扰能力。
余氯传感器模块专门检测水中的余氯浓度,通过电化学原理将氯含量转换为电信号,由STM32进行采集和处理。该模块与主控制器通过杜邦线连接,实现实时数据更新,帮助维持水质安全。
浊度传感器模块测量水质的清澈度,利用光学原理检测悬浮颗粒物,输出信号经STM32解析后得到浊度数值。该模块集成在接口电路中,通过杜邦线与主控制器相连,提供可靠的水质评估数据。
ESP8266-01S Wi-Fi模块实现无线通信功能,连接至华为云平台,使得水质数据能够实时上传和远程访问。STM32通过串口与Wi-Fi模块通信,确保数据稳定传输,并支持云端指令接收和设备状态同步。
自动控制功能由STM32通过输出引脚驱动外部水质调节设备,如加药泵或过滤器,根据监测到的pH、余氯和浊度数据自动调整设备运行状态。这一过程基于预设阈值,实现智能化水质维护。
水质数据异常预警和记录功能由STM32实现,当检测到pH、余氯或浊度参数超出安全范围时,系统会触发本地预警并通过Wi-Fi模块上报至云平台,同时将异常事件记录在存储器中,便于后续分析和追溯。
QT上位机显示系统通过从华为云平台获取数据,实时展示水质参数的变化趋势和设备运行状态。该界面以图表和数值形式呈现信息,为用户提供直观的监控体验,并支持历史数据查询和报警通知。
上位机代码设计
// main.cpp
#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QTextEdit>
#include <QTabWidget>
#include <QChartView>
#include <QLineSeries>
#include <QDateTimeAxis>
#include <QValueAxis>
#include <QTimer>
#include <QDateTime>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QtMqtt/QMqttClient>
#include <QJsonDocument>
#include <QJsonObject>
QT_CHARTS_USE_NAMESPACE
class WaterQualityMonitor : public QMainWindow
{
Q_OBJECT
public:
WaterQualityMonitor(QWidget *parent = nullptr)
: QMainWindow(parent)
{
setupUI();
setupMQTT();
setupCharts();
setupTimer();
}
private slots:
void onConnected();
void onMessageReceived(const QByteArray &message, const QMqttTopicName &topic);
void updateRealtimeData();
void saveDataToFile();
void checkAlarms();
private:
void setupUI();
void setupMQTT();
void setupCharts();
void setupTimer();
// MQTT客户端
QMqttClient *m_client;
// UI组件
QTabWidget *m_tabWidget;
// 实时数据显示
QLabel *m_phValueLabel;
QLabel *m_chlorineValueLabel;
QLabel *m_turbidityValueLabel;
QLabel *m_statusLabel;
QTextEdit *m_logTextEdit;
// 图表
QChart *m_phChart;
QChart *m_chlorineChart;
QChart *m_turbidityChart;
QLineSeries *m_phSeries;
QLineSeries *m_chlorineSeries;
QLineSeries *m_turbiditySeries;
// 数据存储
QVector<QPointF> m_phData;
QVector<QPointF> m_chlorineData;
QVector<QPointF> m_turbidityData;
// 定时器
QTimer *m_updateTimer;
QTimer *m_saveTimer;
// 当前数据
double m_currentPH;
double m_currentChlorine;
double m_currentTurbidity;
};
void WaterQualityMonitor::setupUI()
{
setWindowTitle("智能游泳池水质监测系统");
setMinimumSize(1200, 800);
// 创建主窗口部件
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
// 创建标签页
m_tabWidget = new QTabWidget(centralWidget);
// 实时监控页面
QWidget *realtimeTab = new QWidget();
QVBoxLayout *realtimeLayout = new QVBoxLayout(realtimeTab);
// 数据显示区域
QGridLayout *dataLayout = new QGridLayout();
dataLayout->addWidget(new QLabel("pH值:"), 0, 0);
m_phValueLabel = new QLabel("--");
m_phValueLabel->setStyleSheet("font-size: 24pt; color: blue;");
dataLayout->addWidget(m_phValueLabel, 0, 1);
dataLayout->addWidget(new QLabel("余氯浓度(mg/L):"), 1, 0);
m_chlorineValueLabel = new QLabel("--");
m_chlorineValueLabel->setStyleSheet("font-size: 24pt; color: green;");
dataLayout->addWidget(m_chlorineValueLabel, 1, 1);
dataLayout->addWidget(new QLabel("浊度(NTU):"), 2, 0);
m_turbidityValueLabel = new QLabel("--");
m_turbidityValueLabel->setStyleSheet("font-size: 24pt; color: orange;");
dataLayout->addWidget(m_turbidityValueLabel, 2, 1);
dataLayout->addWidget(new QLabel("系统状态:"), 3, 0);
m_statusLabel = new QLabel("等待连接...");
m_statusLabel->setStyleSheet("font-size: 16pt; color: gray;");
dataLayout->addWidget(m_statusLabel, 3, 1);
realtimeLayout->addLayout(dataLayout);
// 日志区域
realtimeLayout->addWidget(new QLabel("系统日志:"));
m_logTextEdit = new QTextEdit();
m_logTextEdit->setMaximumHeight(200);
realtimeLayout->addWidget(m_logTextEdit);
// 趋势图表页面
QWidget *chartTab = new QWidget();
QVBoxLayout *chartLayout = new QVBoxLayout(chartTab);
// pH值图表
QChartView *phChartView = new QChartView();
phChartView->setRenderHint(QPainter::Antialiasing);
chartLayout->addWidget(new QLabel("pH值变化趋势:"));
chartLayout->addWidget(phChartView);
// 余氯浓度图表
QChartView *chlorineChartView = new QChartView();
chlorineChartView->setRenderHint(QPainter::Antialiasing);
chartLayout->addWidget(new QLabel("余氯浓度变化趋势:"));
chartLayout->addWidget(chlorineChartView);
// 浊度图表
QChartView *turbidityChartView = new QChartView();
turbidityChartView->setRenderHint(QPainter::Antialiasing);
chartLayout->addWidget(new QLabel("浊度变化趋势:"));
chartLayout->addWidget(turbidityChartView);
m_tabWidget->addTab(realtimeTab, "实时监控");
m_tabWidget->addTab(chartTab, "趋势分析");
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
mainLayout->addWidget(m_tabWidget);
}
void WaterQualityMonitor::setupMQTT()
{
m_client = new QMqttClient(this);
m_client->setHostname("your_huawei_cloud_address"); // 替换为实际华为云地址
m_client->setPort(1883);
m_client->setUsername("your_username"); // 替换为实际用户名
m_client->setPassword("your_password"); // 替换为实际密码
connect(m_client, &QMqttClient::connected, this, &WaterQualityMonitor::onConnected);
connect(m_client, &QMqttClient::messageReceived, this, &WaterQualityMonitor::onMessageReceived);
// 连接MQTT服务器
m_client->connectToHost();
}
void WaterQualityMonitor::setupCharts()
{
// pH值图表设置
m_phChart = new QChart();
m_phSeries = new QLineSeries();
m_phChart->addSeries(m_phSeries);
m_phChart->setTitle("pH值监测");
m_phChart->createDefaultAxes();
QDateTimeAxis *axisX = new QDateTimeAxis();
axisX->setTitleText("时间");
axisX->setFormat("hh:mm:ss");
m_phChart->addAxis(axisX, Qt::AlignBottom);
m_phSeries->attachAxis(axisX);
QValueAxis *axisY = new QValueAxis();
axisY->setTitleText("pH值");
axisY->setRange(6.0, 8.5);
m_phChart->addAxis(axisY, Qt::AlignLeft);
m_phSeries->attachAxis(axisY);
// 余氯浓度图表设置
m_chlorineChart = new QChart();
m_chlorineSeries = new QLineSeries();
m_chlorineChart->addSeries(m_chlorineSeries);
m_chlorineChart->setTitle("余氯浓度监测");
m_chlorineChart->createDefaultAxes();
QDateTimeAxis *axisX2 = new QDateTimeAxis();
axisX2->setTitleText("时间");
axisX2->setFormat("hh:mm:ss");
m_chlorineChart->addAxis(axisX2, Qt::AlignBottom);
m_chlorineSeries->attachAxis(axisX2);
QValueAxis *axisY2 = new QValueAxis();
axisY2->setTitleText("余氯浓度(mg/L)");
axisY2->setRange(0.0, 2.0);
m_chlorineChart->addAxis(axisY2, Qt::AlignLeft);
m_chlorineSeries->attachAxis(axisY2);
// 浊度图表设置
m_turbidityChart = new QChart();
m_turbiditySeries = new QLineSeries();
m_turbidityChart->addSeries(m_turbiditySeries);
m_turbidityChart->setTitle("浊度监测");
m_turbidityChart->createDefaultAxes();
QDateTimeAxis *axisX3 = new QDateTimeAxis();
axisX3->setTitleText("时间");
axisX3->setFormat("hh:mm:ss");
m_turbidityChart->addAxis(axisX3, Qt::AlignBottom);
m_turbiditySeries->attachAxis(axisX3);
QValueAxis *axisY3 = new QValueAxis();
axisY3->setTitleText("浊度(NTU)");
axisY3->setRange(0.0, 10.0);
m_turbidityChart->addAxis(axisY3, Qt::AlignLeft);
m_turbiditySeries->attachAxis(axisY3);
// 设置图表视图
QList<QChartView*> chartViews = findChildren<QChartView*>();
if (chartViews.size() >= 3) {
chartViews[0]->setChart(m_phChart);
chartViews[1]->setChart(m_chlorineChart);
chartViews[2]->setChart(m_turbidityChart);
}
}
void WaterQualityMonitor::setupTimer()
{
m_updateTimer = new QTimer(this);
connect(m_updateTimer, &QTimer::timeout, this, &WaterQualityMonitor::updateRealtimeData);
m_updateTimer->start(1000); // 1秒更新一次
m_saveTimer = new QTimer(this);
connect(m_saveTimer, &QTimer::timeout, this, &WaterQualityMonitor::saveDataToFile);
m_saveTimer->start(60000); // 1分钟保存一次数据
}
void WaterQualityMonitor::onConnected()
{
m_statusLabel->setText("已连接到云平台");
m_statusLabel->setStyleSheet("color: green;");
// 订阅主题
m_client->subscribe(QMqttTopicFilter("pool/water/quality"));
m_logTextEdit->append(QDateTime::currentDateTime().toString() +
" - 成功连接到云平台");
}
void WaterQualityMonitor::onMessageReceived(const QByteArray &message, const QMqttTopicName &topic)
{
QJsonDocument doc = QJsonDocument::fromJson(message);
if (doc.isObject()) {
QJsonObject obj = doc.object();
m_currentPH = obj["pH"].toDouble();
m_currentChlorine = obj["chlorine"].toDouble();
m_currentTurbidity = obj["turbidity"].toDouble();
// 更新实时数据显示
m_phValueLabel->setText(QString::number(m_currentPH, 'f', 2));
m_chlorineValueLabel->setText(QString::number(m_currentChlorine, 'f', 2));
m_turbidityValueLabel->setText(QString::number(m_currentTurbidity, 'f', 2));
// 添加到数据序列
qint64 currentTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
m_phData.append(QPointF(currentTime, m_currentPH));
m_chlorineData.append(QPointF(currentTime, m_currentChlorine));
m_turbidityData.append(QPointF(currentTime, m_currentTurbidity));
// 检查警报
checkAlarms();
// 限制数据点数量
if (m_phData.size() > 100) {
m_phData.removeFirst();
m_chlorineData.removeFirst();
m_turbidityData.removeFirst();
}
}
}
void WaterQualityMonitor::updateRealtimeData()
{
// 更新图表数据
m_phSeries->replace(m_phData);
m_chlorineSeries->replace(m_chlorineData);
m_turbiditySeries->replace(m_turbidityData);
}
void WaterQualityMonitor::saveDataToFile()
{
QFile file("water_quality_data.csv");
if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
QTextStream stream(&file);
QDateTime currentTime = QDateTime::currentDateTime();
stream << currentTime.toString("yyyy-MM-dd hh:mm:ss") << ","
<< m_currentPH << ","
<< m_currentChlorine << ","
<< m_currentTurbidity << "\n";
file.close();
}
}
void WaterQualityMonitor::checkAlarms()
{
QString alarmMessage;
// pH值警报 (正常范围: 7.2-7.8)
if (m_currentPH < 7.2 || m_currentPH > 7.8) {
alarmMessage = QString("警告: pH值异常! 当前值: %1 (正常范围: 7.2-7.8)").arg(m_currentPH);
m_logTextEdit->append(QDateTime::currentDateTime().toString() + " - " + alarmMessage);
}
// 余氯浓度警报 (正常范围: 0.3-1.0 mg/L)
if (m_currentChlorine < 0.3 || m_currentChlorine > 1.0) {
alarmMessage = QString("警告: 余氯浓度异常! 当前值: %1 mg/L (正常范围: 0.3-1.0 mg/L)").arg(m_currentChlorine);
m_logTextEdit->append(QDateTime::currentDateTime().toString() + " - " + alarmMessage);
}
// 浊度警报 (正常范围: < 1 NTU)
if (m_currentTurbidity > 1.0) {
alarmMessage = QString("警告: 浊度异常! 当前值: %1 NTU (正常值: < 1 NTU)").arg(m_currentTurbidity);
m_logTextEdit->append(QDateTime::currentDateTime().toString() + " - " + alarmMessage);
}
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
WaterQualityMonitor monitor;
monitor.show();
return app.exec();
}
#include "main.moc"
# WaterQualityMonitor.pro
QT += core gui charts network mqtt
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
TARGET = WaterQualityMonitor
TEMPLATE = app
SOURCES += \
main.cpp
HEADERS +=
# 发布版本配置
CONFIG(release, debug|release) {
DEFINES += QT_NO_DEBUG_OUTPUT
}
# 设置编译选项
win32: {
QMAKE_CXXFLAGS += -O2
QMAKE_LFLAGS += -static
}
# CMakeLists.txt (可选,用于CMake构建)
cmake_minimum_required(VERSION 3.16)
project(WaterQualityMonitor)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Charts Network Mqtt)
qt_standard_project_setup()
qt_add_executable(WaterQualityMonitor
main.cpp
)
qt_add_resources(WaterQualityMonitor "resources"
PREFIX "/"
)
target_link_libraries(WaterQualityMonitor Qt6::Core Qt6::Widgets Qt6::Charts Qt6::Network Qt6::Mqtt)
这个上位机程序提供了以下功能:
-
实时监控界面:
- 显示pH值、余氯浓度、浊度的实时数据
- 系统状态指示
- 系统日志显示
-
趋势分析界面:
- 三个独立的图表分别显示pH值、余氯浓度、浊度的历史变化趋势
- 支持时间轴显示
-
数据管理:
- 自动保存数据到CSV文件
- 实时数据更新和图表刷新
-
报警功能:
- 水质参数异常自动报警
- 报警信息记录到日志
-
云平台通信:
- 通过MQTT协议连接华为云平台
- 实时接收STM32发送的水质数据
使用时需要:
- 配置正确的华为云MQTT服务器地址、端口、用户名和密码
- 确保网络连接正常
- 根据需要调整水质参数的正常范围阈值
模块代码设计
#include "stm32f10x.h"
// 传感器引脚定义
#define PH_SENSOR_PIN GPIO_Pin_0 // PA0 - pH传感器
#define CL_SENSOR_PIN GPIO_Pin_1 // PA1 - 余氯传感器
#define TURB_SENSOR_PIN GPIO_Pin_2 // PA2 - 浊度传感器
#define RELAY_PH_UP GPIO_Pin_0 // PB0 - pH上调继电器
#define RELAY_PH_DOWN GPIO_Pin_1 // PB1 - pH下调继电器
#define RELAY_CHLORINE GPIO_Pin_2 // PB2 - 加氯继电器
#define RELAY_FILTER GPIO_Pin_3 // PB3 - 过滤泵继电器
// 传感器数据结构
typedef struct {
float pH_value;
float chlorine_value;
float turbidity_value;
uint8_t ph_status;
uint8_t chlorine_status;
uint8_t turbidity_status;
} SensorData;
SensorData water_data;
uint8_t wifi_connected = 0;
// ADC初始化
void ADC_Configuration(void)
{
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // 使能ADC1时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // 使能GPIOA时钟
// 配置PA0, PA1, PA2为模拟输入
GPIOA->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_MODE0 |
GPIO_CRL_CNF1 | GPIO_CRL_MODE1 |
GPIO_CRL_CNF2 | GPIO_CRL_MODE2);
GPIOA->CRL |= (GPIO_CRL_CNF0_0 | GPIO_CRL_CNF1_0 | GPIO_CRL_CNF2_0);
// ADC配置
ADC1->CR2 = 0;
ADC1->CR2 |= ADC_CR2_ADON; // 开启ADC
ADC1->CR2 |= ADC_CR2_CAL; // 开始校准
while(ADC1->CR2 & ADC_CR2_CAL); // 等待校准完成
ADC1->SQR1 = 0; // 1个转换
ADC1->SQR3 = 0; // 通道0
ADC1->SMPR2 = ADC_SMPR2_SMP0_2 | // 通道0采样时间239.5周期
ADC_SMPR2_SMP1_2 | // 通道1采样时间239.5周期
ADC_SMPR2_SMP2_2; // 通道2采样时间239.5周期
}
// 读取ADC值
uint16_t ADC_Read(uint8_t channel)
{
ADC1->SQR3 = channel; // 设置转换通道
ADC1->CR2 |= ADC_CR2_ADON; // 开始转换
while(!(ADC1->SR & ADC_SR_EOC)); // 等待转换完成
return ADC1->DR; // 返回转换结果
}
// pH传感器读取和校准
float Read_pH_Sensor(void)
{
uint32_t sum = 0;
uint16_t adc_value;
float voltage, pH_value;
// 读取16次取平均
for(int i = 0; i < 16; i++) {
adc_value = ADC_Read(0); // 通道0 - pH传感器
sum += adc_value;
for(int j = 0; j < 1000; j++); // 短暂延时
}
adc_value = sum >> 4; // 求平均值
voltage = (float)adc_value * 3.3 / 4096.0; // 转换为电压
// pH值计算 (PH-4502C特性曲线)
// 实际应用中需要根据传感器手册进行校准
pH_value = 3.5 * voltage + 2.0; // 简化计算公式
return pH_value;
}
// 余氯传感器读取
float Read_Chlorine_Sensor(void)
{
uint32_t sum = 0;
uint16_t adc_value;
float voltage, chlorine_value;
for(int i = 0; i < 16; i++) {
adc_value = ADC_Read(1); // 通道1 - 余氯传感器
sum += adc_value;
for(int j = 0; j < 1000; j++);
}
adc_value = sum >> 4;
voltage = (float)adc_value * 3.3 / 4096.0;
// 余氯浓度计算 (mg/L)
chlorine_value = voltage * 2.0; // 简化计算公式
return chlorine_value;
}
// 浊度传感器读取
float Read_Turbidity_Sensor(void)
{
uint32_t sum = 0;
uint16_t adc_value;
float voltage, turbidity_value;
for(int i = 0; i < 16; i++) {
adc_value = ADC_Read(2); // 通道2 - 浊度传感器
sum += adc_value;
for(int j = 0; j < 1000; j++);
}
adc_value = sum >> 4;
voltage = (float)adc_value * 3.3 / 4096.0;
// 浊度计算 (NTU)
turbidity_value = (3.0 - voltage) * 500.0; // 简化计算公式
return turbidity_value;
}
// GPIO初始化
void GPIO_Configuration(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // 使能GPIOB时钟
// 配置PB0-PB3为推挽输出 (继电器控制)
GPIOB->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_MODE0 |
GPIO_CRL_CNF1 | GPIO_CRL_MODE1 |
GPIO_CRL_CNF2 | GPIO_CRL_MODE2 |
GPIO_CRL_CNF3 | GPIO_CRL_MODE3);
GPIOB->CRL |= (GPIO_CRL_MODE0_0 | GPIO_CRL_MODE0_1 |
GPIO_CRL_MODE1_0 | GPIO_CRL_MODE1_1 |
GPIO_CRL_MODE2_0 | GPIO_CRL_MODE2_1 |
GPIO_CRL_MODE3_0 | GPIO_CRL_MODE3_1);
}
// USART2初始化 (ESP8266通信)
void USART2_Configuration(void)
{
RCC->APB1ENR |= RCC_APB1ENR_USART2EN; // 使能USART2时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // 使能GPIOA时钟
// 配置PA2为推挽输出 (TX)
GPIOA->CRL &= ~(GPIO_CRL_CNF2 | GPIO_CRL_MODE2);
GPIOA->CRL |= GPIO_CRL_CNF2_1 | GPIO_CRL_MODE2_0 | GPIO_CRL_MODE2_1;
// 配置PA3为浮空输入 (RX)
GPIOA->CRL &= ~(GPIO_CRL_CNF3 | GPIO_CRL_MODE3);
GPIOA->CRL |= GPIO_CRL_CNF3_0;
// 波特率设置 115200
USART2->BRR = 72000000 / 115200;
// 使能发送和接收
USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}
// USART发送字符
void USART2_SendChar(char ch)
{
while(!(USART2->SR & USART_SR_TXE)); // 等待发送缓冲区空
USART2->DR = ch;
}
// USART发送字符串
void USART2_SendString(char *str)
{
while(*str) {
USART2_SendChar(*str++);
}
}
// 继电器控制函数
void Control_Relay(uint8_t relay, uint8_t state)
{
if(state) {
GPIOB->BSRR = (1 << relay); // 置位,打开继电器
} else {
GPIOB->BRR = (1 << relay); // 复位,关闭继电器
}
}
// 水质自动控制
void Water_Quality_Control(void)
{
// pH控制 (理想范围: 7.2-7.8)
if(water_data.pH_value < 7.2) {
Control_Relay(0, 1); // 打开pH上调
Control_Relay(1, 0); // 关闭pH下调
water_data.ph_status = 1; // pH偏低
} else if(water_data.pH_value > 7.8) {
Control_Relay(0, 0); // 关闭pH上调
Control_Relay(1, 1); // 打开pH下调
water_data.ph_status = 2; // pH偏高
} else {
Control_Relay(0, 0); // 关闭pH上调
Control_Relay(1, 0); // 关闭pH下调
water_data.ph_status = 0; // pH正常
}
// 余氯控制 (理想范围: 1.0-3.0 mg/L)
if(water_data.chlorine_value < 1.0) {
Control_Relay(2, 1); // 打开加氯
water_data.chlorine_status = 1; // 余氯偏低
} else if(water_data.chlorine_value > 3.0) {
Control_Relay(2, 0); // 关闭加氯
water_data.chlorine_status = 2; // 余氯偏高
} else {
Control_Relay(2, 0); // 关闭加氯
water_data.chlorine_status = 0; // 余氯正常
}
// 浊度控制 (理想范围: 0-5 NTU)
if(water_data.turbidity_value > 5.0) {
Control_Relay(3, 1); // 打开过滤泵
water_data.turbidity_status = 1; // 浊度偏高
} else {
Control_Relay(3, 0); // 关闭过滤泵
water_data.turbidity_status = 0; // 浊度正常
}
}
// ESP8266发送数据到云平台
void Send_Data_To_Cloud(void)
{
char buffer[128];
// 构造JSON格式数据
sprintf(buffer, "{\"pH\":%.2f,\"chlorine\":%.2f,\"turbidity\":%.2f,\"status\":%d}",
water_data.pH_value, water_data.chlorine_value,
water_data.turbidity_value, wifi_connected);
USART2_SendString("AT+CIPSEND=0,");
USART2_SendString(buffer);
USART2_SendString("\r\n");
}
// 系统时钟初始化
void RCC_Configuration(void)
{
// 启用HSE
RCC->CR |= RCC_CR_HSEON;
while(!(RCC->CR & RCC_CR_HSERDY));
// 配置PLL
RCC->CFGR |= RCC_CFGR_PLLSRC; // PLL源选择HSE
RCC->CFGR |= RCC_CFGR_PLLMULL9; // PLL倍频9倍 (8MHz * 9 = 72MHz)
// 启用PLL
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));
// 配置Flash预取指
FLASH->ACR |= FLASH_ACR_PRFTBE;
FLASH->ACR |= FLASH_ACR_LATENCY_2;
// 切换系统时钟到PLL
RCC->CFGR |= RCC_CFGR_SW_PLL;
while(!(RCC->CFGR & RCC_CFGR_SWS_PLL));
}
// 延时函数
void Delay(uint32_t count)
{
for(uint32_t i = 0; i < count; i++);
}
// 系统初始化
void System_Init(void)
{
RCC_Configuration();
GPIO_Configuration();
ADC_Configuration();
USART2_Configuration();
// 初始化所有继电器为关闭状态
Control_Relay(0, 0);
Control_Relay(1, 0);
Control_Relay(2, 0);
Control_Relay(3, 0);
}
int main(void)
{
System_Init();
while(1) {
// 读取传感器数据
water_data.pH_value = Read_pH_Sensor();
water_data.chlorine_value = Read_Chlorine_Sensor();
water_data.turbidity_value = Read_Turbidity_Sensor();
// 水质自动控制
Water_Quality_Control();
// 发送数据到云平台
if(wifi_connected) {
Send_Data_To_Cloud();
}
// 延时5秒
Delay(5000000);
}
}
// ESP8266接收中断处理
void USART2_IRQHandler(void)
{
if(USART2->SR & USART_SR_RXNE) {
uint8_t data = USART2->DR;
// 处理Wi-Fi模块响应
if(data == 'O' || data == 'K') {
wifi_connected = 1;
}
}
}
项目核心代码
#include "stm32f10x.h"
// 传感器数据结构体
typedef struct {
float ph_value;
float chlorine_value;
float turbidity_value;
} SensorData;
// 设备控制结构体
typedef struct {
uint8_t ph_control;
uint8_t chlorine_control;
uint8_t filter_control;
} DeviceControl;
// 全局变量
SensorData current_data;
DeviceControl device_status;
uint32_t system_tick = 0;
// 函数声明
void System_Init(void);
void GPIO_Init(void);
void ADC_Init(void);
void USART_Init(void);
void TIM_Init(void);
void ESP8266_SendData(SensorData data);
void Device_Control(SensorData data);
void Alert_Check(SensorData data);
float Read_PH_Sensor(void);
float Read_Chlorine_Sensor(void);
float Read_Turbidity_Sensor(void);
int main(void)
{
// 系统初始化
System_Init();
while(1)
{
// 每1秒执行一次主循环
if(system_tick >= 1000)
{
system_tick = 0;
// 读取传感器数据
current_data.ph_value = Read_PH_Sensor();
current_data.chlorine_value = Read_Chlorine_Sensor();
current_data.turbidity_value = Read_Turbidity_Sensor();
// 发送数据到云平台
ESP8266_SendData(current_data);
// 设备控制
Device_Control(current_data);
// 异常预警检查
Alert_Check(current_data);
}
}
}
// 系统初始化
void System_Init(void)
{
// 设置系统时钟
RCC->CR |= 0x00010000; // HSEON
while(!(RCC->CR & 0x00020000)); // 等待HSE就绪
RCC->CFGR = 0x00010000; // PLL输入时钟源为HSE
RCC->CFGR |= 0x001C0000; // PLL倍频系数9
RCC->CR |= 0x01000000; // PLLON
while(!(RCC->CR & 0x02000000)); // 等待PLL就绪
FLASH->ACR |= 0x12; // Flash等待状态
RCC->CFGR |= 0x00000002; // PLL作为系统时钟
while((RCC->CFGR & 0x08) != 0x08); // 等待切换完成
// 初始化各外设
GPIO_Init();
ADC_Init();
USART_Init();
TIM_Init();
}
// GPIO初始化
void GPIO_Init(void)
{
// 使能GPIO时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN;
// PA0, PA1, PA2 作为模拟输入 (pH, 余氯, 浊度传感器)
GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0 |
GPIO_CRL_MODE1 | GPIO_CRL_CNF1 |
GPIO_CRL_MODE2 | GPIO_CRL_CNF2);
GPIOA->CRL |= (GPIO_CRL_CNF0_0 | GPIO_CRL_CNF1_0 | GPIO_CRL_CNF2_0);
// PC13, PC14, PC15 作为输出 (设备控制)
GPIOC->CRH &= ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13 |
GPIO_CRH_MODE14 | GPIO_CRH_CNF14 |
GPIO_CRH_MODE15 | GPIO_CRH_CNF15);
GPIOC->CRH |= (GPIO_CRH_MODE13_0 | GPIO_CRH_MODE14_0 | GPIO_CRH_MODE15_0);
// PA9(TX), PA10(RX) 作为USART1
GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9 |
GPIO_CRH_MODE10 | GPIO_CRH_CNF10);
GPIOA->CRH |= (GPIO_CRH_MODE9_1 | GPIO_CRH_CNF9_1 | // PA9: 输出50MHz, 复用推挽
GPIO_CRH_CNF10_0); // PA10: 浮空输入
}
// ADC初始化
void ADC_Init(void)
{
// 使能ADC1时钟
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
// ADC校准
ADC1->CR2 |= ADC_CR2_ADON;
delay_ms(1);
ADC1->CR2 |= ADC_CR2_CAL;
while(ADC1->CR2 & ADC_CR2_CAL);
// 配置ADC
ADC1->CR1 = 0;
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CONT; // 连续转换模式
ADC1->SMPR2 = (ADC_SMPR2_SMP0_2 | ADC_SMPR2_SMP0_1 | // 通道0采样时间239.5周期
ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1 | // 通道1采样时间239.5周期
ADC_SMPR2_SMP2_2 | ADC_SMPR2_SMP2_1); // 通道2采样时间239.5周期
}
// USART初始化 (用于ESP8266通信)
void USART_Init(void)
{
// 使能USART1时钟
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// 配置波特率 115200
USART1->BRR = 390; // 72MHz / 115200 = 625, 625/16=39.0625
// 配置控制寄存器
USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; // 使能USART, 发送, 接收
USART1->CR2 = 0;
USART1->CR3 = 0;
}
// 定时器初始化
void TIM_Init(void)
{
// 使能TIM2时钟
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
// 配置TIM2 1ms中断
TIM2->PSC = 7200 - 1; // 72MHz/7200 = 10kHz
TIM2->ARR = 10 - 1; // 10kHz/10 = 1kHz = 1ms
TIM2->DIER = TIM_DIER_UIE; // 使能更新中断
TIM2->CR1 = TIM_CR1_CEN; // 使能定时器
// 配置NVIC
NVIC->ISER[0] |= (1 << TIM2_IRQn);
NVIC->IP[TIM2_IRQn] = 0x10;
}
// 读取pH传感器
float Read_PH_Sensor(void)
{
ADC1->SQR3 = 0; // 通道0
ADC1->CR2 |= ADC_CR2_SWSTART;
while(!(ADC1->SR & ADC_SR_EOC));
uint16_t adc_value = ADC1->DR;
return (adc_value * 3.3f / 4096.0f) * 2.0f + 4.0f; // 转换为pH值
}
// 读取余氯传感器
float Read_Chlorine_Sensor(void)
{
ADC1->SQR3 = 1; // 通道1
ADC1->CR2 |= ADC_CR2_SWSTART;
while(!(ADC1->SR & ADC_SR_EOC));
uint16_t adc_value = ADC1->DR;
return (adc_value * 3.3f / 4096.0f) * 5.0f; // 转换为余氯浓度(mg/L)
}
// 读取浊度传感器
float Read_Turbidity_Sensor(void)
{
ADC1->SQR3 = 2; // 通道2
ADC1->CR2 |= ADC_CR2_SWSTART;
while(!(ADC1->SR & ADC_SR_EOC));
uint16_t adc_value = ADC1->DR;
return (adc_value * 3.3f / 4096.0f) * 100.0f; // 转换为浊度值(NTU)
}
// 发送数据到ESP8266
void ESP8266_SendData(SensorData data)
{
char buffer[128];
sprintf(buffer, "{\"pH\":%.2f,\"chlorine\":%.2f,\"turbidity\":%.2f}\r\n",
data.ph_value, data.chlorine_value, data.turbidity_value);
for(int i = 0; buffer[i] != '\0'; i++)
{
USART1->DR = buffer[i];
while(!(USART1->SR & USART_SR_TXE));
}
}
// 设备控制
void Device_Control(SensorData data)
{
// pH控制 (目标范围7.2-7.6)
if(data.ph_value < 7.2f)
{
GPIOC->BSRR = GPIO_BSRR_BS13; // 开启pH调节设备
device_status.ph_control = 1;
}
else if(data.ph_value > 7.6f)
{
GPIOC->BSRR = GPIO_BSRR_BR13; // 关闭pH调节设备
device_status.ph_control = 0;
}
// 余氯控制 (目标范围1.0-3.0 mg/L)
if(data.chlorine_value < 1.0f)
{
GPIOC->BSRR = GPIO_BSRR_BS14; // 开启加氯设备
device_status.chlorine_control = 1;
}
else if(data.chlorine_value > 3.0f)
{
GPIOC->BSRR = GPIO_BSRR_BR14; // 关闭加氯设备
device_status.chlorine_control = 0;
}
// 过滤控制 (浊度>5时开启)
if(data.turbidity_value > 5.0f)
{
GPIOC->BSRR = GPIO_BSRR_BS15; // 开启过滤设备
device_status.filter_control = 1;
}
else
{
GPIOC->BSRR = GPIO_BSRR_BR15; // 关闭过滤设备
device_status.filter_control = 0;
}
}
// 异常预警检查
void Alert_Check(SensorData data)
{
if(data.ph_value < 6.8f || data.ph_value > 8.0f ||
data.chlorine_value < 0.5f || data.chlorine_value > 5.0f ||
data.turbidity_value > 10.0f)
{
// 发送预警信息
char alert_msg[64];
sprintf(alert_msg, "ALERT: pH=%.2f, Cl=%.2f, Turb=%.2f\r\n",
data.ph_value, data.chlorine_value, data.turbidity_value);
for(int i = 0; alert_msg[i] != '\0'; i++)
{
USART1->DR = alert_msg[i];
while(!(USART1->SR & USART_SR_TXE));
}
}
}
// TIM2中断服务函数
void TIM2_IRQHandler(void)
{
if(TIM2->SR & TIM_SR_UIF)
{
TIM2->SR &= ~TIM_SR_UIF;
system_tick++;
}
}
// 简单延时函数
void delay_ms(uint32_t ms)
{
for(uint32_t i = 0; i < ms * 1000; i++)
{
__NOP();
}
}
总结
该系统基于STM32F103C8T6微控制器设计,实现了对游泳池水质的智能化监测与管理。通过集成pH、余氯和浊度传感器,系统能够实时采集关键水质参数,并自动控制调节设备运行,确保水质始终处于安全范围内。
硬件部分采用模块化结构,包括STM32核心板、PH-4502C传感器、余氯模块和浊度传感器,通过洞洞板电路和杜邦线可靠连接。ESP8266-01S Wi-Fi模块实现了与华为云平台的数据交互,为远程监控提供了基础支持。
系统具备数据异常预警和记录功能,当检测到参数超标时能及时触发警报并存储历史数据。结合QT开发的上位机界面,用户可直观查看水质趋势图和设备状态,提升了管理效率和系统可靠性。
整体设计兼顾实用性与扩展性,为游泳池水质维护提供了一套低成本、高精度的自动化解决方案,未来可通过软件升级进一步优化数据分析能力。
- 点赞
- 收藏
- 关注作者
评论(0)