基于STM32的智能垃圾桶监控系统设计
项目开发背景
项目开发背景
随着城市化进程加速和人口密度不断提高,生活垃圾产量持续增长,传统垃圾桶管理面临严峻挑战。人工巡查方式效率低下、响应滞后,常出现垃圾满溢未及时清理的情况,不仅影响环境卫生,滋生蚊虫细菌,还可能因异味扩散引发居民投诉,增加城市管理成本。同时,垃圾分类政策的推行也对垃圾桶状态监控提出了更高要求。
物联网(IoT)和嵌入式技术的快速发展为解决上述问题提供了新思路。通过将感知、通信与控制技术融入传统垃圾桶,构建智能监控系统,可实现对垃圾容量、开盖状态等关键信息的实时采集与远程管理,大幅提升环卫作业的精准性和效率。这种智能化改造契合智慧城市建设目标,是优化公共资源配置、改善人居环境的重要环节。
本项目基于STM32微控制器设计智能垃圾桶监控系统,旨在解决传统垃圾管理痛点。系统利用超声波传感器精准检测桶内满溢状态,通过红外感应自动触发开盖机制提升用户体验,并结合OLED屏提供本地状态反馈。更重要的是,借助WiFi模块将数据实时上传至华为云物联网平台,使管理人员或居民可通过手机APP远程查看垃圾桶状态、开盖次数等关键信息,为垃圾清运路线优化、资源调度提供数据支撑,推动城市环卫管理向智能化、精细化、高效化方向转型。
设计实现的功能
(1)检测垃圾桶满溢状态并上传数据
(2)检测开盖状态与投放次数统计
(3)自动开盖(红外检测 + 舵机控制)
(4)本地OLED显示桶状态
(5)数据上传至华为云物联网平台,APP可远程查看
项目硬件模块组成
(1)主控芯片:STM32F103C8T6
(2)开盖检测模块:红外对管
(3)满溢检测模块:超声波模块HC-SR04
(4)驱动模块:SG90舵机
(5)显示模块:0.96寸SPI OLED
(6)联网模块:ESP8266 WiFi模块
(7)供电模块:DC 5V输入 + AMS1117稳压模块
设计意义
基于STM32的智能垃圾桶监控系统具有以下设计意义:
该系统显著提升了垃圾桶管理的效率和智能化水平。通过超声波模块实时监测垃圾满溢状态,系统能及时上传数据,有效避免了垃圾溢出造成的环境污染和公共卫生问题。管理人员可依据准确信息优化清运路线和频次,大幅减少无效巡检,降低人力与运营成本。
红外对管检测开盖状态并统计投放次数,结合舵机实现的自动开盖功能,极大改善了用户体验。用户无需手动接触桶盖即可投放垃圾,既提升了便捷性又增强了卫生安全性,尤其利于行动不便者。投放数据还可为垃圾量预测和行为分析提供依据。
本地OLED显示屏直观呈现垃圾桶状态(如满溢、开合),方便用户及现场维护人员快速获取关键信息。同时,通过ESP8266模块将状态数据稳定上传至华为云物联网平台,实现了垃圾桶的远程数字化管理。管理者或用户可通过定制开发的Qt APP远程查看多点位垃圾桶实时状态,为城市环卫资源动态调度和精细化管理提供数据支撑。
该设计推动了城市基础设施的智能化升级,通过物联网技术将传统垃圾桶转化为可感知、可交互的节点。及时清理满溢垃圾能有效减少异味扩散和蚊虫滋生,优化后的清运路线也有助于降低车辆能耗与碳排放,从而改善社区及公共环境质量,促进绿色低碳城市发展。
系统采用STM32F103C8T6作为核心控制器,结合成熟可靠的传感器模块(如HC-SR04、红外对管、SG90舵机),在保证功能稳定实现的同时具有较高的性价比和工程可行性,为智慧环卫的实际部署提供了实用化解决方案。
设计思路
设计思路:
本系统以STM32F103C8T6为主控核心,通过多模块协同实现智能监控功能。首先通过超声波模块HC-SR04实时监测桶内垃圾高度,安装在桶顶向下发射超声波,根据回波时间计算距离并设置满溢阈值(如距离<15cm判定为满溢),该状态数据与开盖状态同步更新至OLED显示。
开盖检测采用红外对管安装在桶盖边缘,当桶盖开启时阻断红外信号,触发中断记录开盖事件并累加投放次数计数器。自动开盖功能通过另一组红外模块(桶前侧)检测人体接近信号,触发STM32输出PWM信号驱动SG90舵机实现0-90°转动控制盖体,延时后自动复位。
数据通信通过串口连接ESP8266模块,采用AT指令集建立WiFi连接。STM32将满溢状态、开盖次数等数据封装为JSON格式,通过MQTT协议按设定频率上传至华为云物联网平台,遵循华为云设备接入规范定义数据上报topic。
本地显示使用SPI接口驱动0.96寸OLED,实时刷新桶状态(空/半满/满)、开盖次数、联网状态等关键参数。供电系统采用5V直流输入,经AMS1117-3.3稳压芯片转换后为各模块提供稳定电压,确保系统可靠运行。
框架图
智能垃圾桶监控系统框架图
+--------------------------------------------------------------------+
| 应用层(远程交互) |
| +------------------------------------+ |
| | Qt开发Android/PC APP | |
| | (实时查看状态/报警/历史数据) | |
| +------------------------------------+ |
| | MQTT/HTTP |
| ↓ |
+-------------------------------华为云物联网平台------------------------+
| (数据存储/设备管理/规则引擎) |
| | MQTT协议 |
| ↓ |
+--------------------------------------------------------------------+
| 网络层(数据传输) |
| +------------------------------------+ |
| | ESP8266 WiFi模块 |?---┐ |
| | (AT指令透传/UART通信) | | |
| +------------------------------------+ | |
| | UART串口 | |
| ↓ (PA9-TX, PA10-RX) | |
+--------------------------------------------------------------------+
| 控制层(核心处理) |
| +------------------+ +------------------+ +------------------+ |
| | 满溢检测模块 | | 开盖检测模块 | | 自动开盖执行 | |
| | HC-SR04超声波 | | 红外对管传感器 | | SG90舵机 | |
| | Trig: PA1 | | 信号输入: PA0 | | 控制线: PA3 | |
| | Echo: PA2 | | (统计投放次数) | | (红外触发时动作) | |
| +------------------+ +------------------+ +------------------+ |
| | |
| +--------------------+--------------------+ |
| | STM32F103C8T6 主控芯片 | |
| | (处理数据/逻辑控制/通信调度) |---------┘
| +--------------------+--------------------+
| | SPI接口
| +------------------------------------+
| | 显示模块 |
| | 0.96寸SPI OLED |
| | CS: PA4, SCK: PA5, MOSI: PA7 |
| | DC: PB0, RES: PB1 |
| | (本地显示状态/报警信息) |
| +------------------------------------+
+--------------------------------------------------------------------+
| 供电层(能源管理) |
| +------------------------------------+ |
| | DC 5V输入 → AMS1117稳压模块 | |
| | 输出: 3.3V (主控/传感器) | |
| | 5V (舵机直接供电) | |
| +------------------------------------+ |
+--------------------------------------------------------------------+
框架说明:
- 应用层
- Qt开发的APP通过华为云平台获取实时数据
- 网络层
- ESP8266通过UART与STM32通信,使用MQTT协议上传数据
- 控制层
- STM32协调所有模块:
- 超声波测距判断满溢(PA1/PA2)
- 红外对管检测开盖状态(PA0)
- 舵机控制自动开盖(PA3-PWM)
- OLED显示实时状态(SPI接口)
- STM32协调所有模块:
- 供电层
- AMS1117提供3.3V稳定电压,舵机直接使用5V供电
系统总体设计
系统总体设计
本系统以STM32F103C8T6微控制器为核心,构建智能垃圾桶监控体系。通过多模块协同工作实现功能需求:系统利用超声波模块(HC-SR04)监测垃圾高度,当检测到桶内垃圾达到预设满溢阈值时,触发满溢状态标志。开盖状态检测采用红外对管,实时监测桶盖开闭状态,并基于状态变化统计用户投放次数。
自动开盖功能通过红外人体感应模块实现:当检测到用户靠近时,STM32输出PWM信号驱动SG90舵机转动,完成开盖动作;延时后自动关闭桶盖。本地状态显示由0.96寸SPI OLED模块承担,实时展示桶内满溢状态、开盖状态及投放次数等关键信息。
数据上传通过ESP8266 WiFi模块实现:STM32通过串口通信将满溢状态、开盖状态及投放次数等数据封装为华为云物联网平台协议格式,经ESP8266上传至云端。远程用户可通过Qt开发的Android APP或PC端程序访问华为云平台,实时查看垃圾桶状态数据。
供电系统采用5V直流电源输入,经AMS1117稳压模块转换为3.3V,为STM32、传感器及OLED模块提供稳定工作电压;舵机直接由5V电源驱动。各硬件模块通过杜邦线与主控板连接,形成完整的闭环监控系统。
系统功能总结
功能需求 | 硬件模块 | 实现说明 |
---|---|---|
检测垃圾桶满溢状态并上传数据 | 超声波模块 HC-SR04 + ESP8266 | 超声波测量垃圾高度,通过 WiFi 上传满溢状态至云端 |
检测开盖状态与投放次数统计 | 红外对管 | 红外对管监测桶盖开闭,统计开盖次数作为投放记录 |
自动开盖(红外检测 + 舵机控制) | 红外对管 + SG90 舵机 | 检测人体靠近时触发舵机开盖,延时后自动关闭 |
本地 OLED 显示桶状态 | 0.96 寸 SPI OLED | 实时显示满溢状态、开盖次数、联网状态等信息 |
数据上传至华为云,APP 远程查看 | ESP8266 WiFi 模块 | 连接华为云物联网平台,支持 Qt 开发的 APP 远程监控 |
设计的各个功能模块描述
主控芯片模块
基于STM32F103C8T6微控制器构建系统核心,负责协调所有外设模块的数据采集、逻辑控制与通信调度。通过GPIO、定时器、UART、SPI等接口连接传感器和执行器,实现实时数据处理与任务管理。
开盖检测与统计模块
采用红外对管检测垃圾桶盖的物理开闭状态:当红外光束被遮挡时判定为开盖动作,触发STM32中断并记录一次投放事件。STM32内部计数器累计投放次数,结合防抖算法确保统计准确性,状态数据同步更新至本地显示与云端。
满溢检测模块
通过HC-SR04超声波模块监测桶内垃圾高度。STM32触发超声波发射并计算回波时间差,转换为垃圾表面到桶盖的距离。预设满溢阈值(如距离≤10cm),超限时标记满溢状态,触发本地告警并上传数据。
自动开盖驱动模块
由红外人体感应与SG90舵机协同实现自动开盖:当红外模块检测到用户靠近时,STM32生成PWM信号驱动舵机旋转至预设开盖角度;延时后控制舵机复位闭盖。舵机动作范围通过定时器精准控制,确保开盖流畅性。
本地显示模块
0.96寸SPI OLED实时展示桶状态:通过STM32的SPI接口驱动,动态显示开闭状态(图标)、满溢百分比(进度条)、当日投放次数及WiFi连接标志。界面采用自定义图形库刷新,确保低功耗与高响应速度。
云端通信模块
ESP8266 WiFi模块通过UART与STM32交互,基于AT指令集连接路由器并接入华为云物联网平台。STM32将桶状态、满溢标志及投放次数封装为JSON数据,经MQTT协议上传至云平台指定Topic;同时订阅云端指令,实现远程监控与控制。
远程监控界面
基于Qt框架开发跨平台应用(Android/PC),对接华为云API获取实时数据。界面可视化展示垃圾桶开盖状态、满溢报警、历史投放统计及地理位置信息,支持远程手动开盖指令下发,实现多终端数据同步管理。
供电模块
外部DC 5V电源输入,经AMS1117-3.3稳压芯片转换为稳定3.3V电压,为STM32、ESP8266、传感器及OLED供电;舵机直接由5V驱动,避免稳压芯片过载。电源路径添加滤波电容,确保系统抗干扰能力。
上位机代码设计
基于STM32的智能垃圾桶监控系统 - 上位机设计
下面是一个完整的Qt上位机程序,用于监控智能垃圾桶状态并显示在PC端界面:
#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QProgressBar>
#include <QGroupBox>
#include <QStatusBar>
#include <QDateTime>
#include <QTimer>
#include <QChart>
#include <QChartView>
#include <QLineSeries>
#include <QValueAxis>
#include <QtMqtt/QMqttClient>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QMessageBox>
QT_CHARTS_USE_NAMESPACE
class SmartTrashMonitor : public QMainWindow {
Q_OBJECT
public:
SmartTrashMonitor(QWidget *parent = nullptr) : QMainWindow(parent) {
// 初始化MQTT客户端
mqttClient = new QMqttClient(this);
mqttClient->setHostname("your_huawei_iot_host");
mqttClient->setPort(1883);
mqttClient->setClientId("PC_Monitor");
mqttClient->setUsername("device_username");
mqttClient->setPassword("device_password");
// 连接信号槽
connect(mqttClient, &QMqttClient::connected, this, &SmartTrashMonitor::onConnected);
connect(mqttClient, &QMqttClient::disconnected, this, &SmartTrashMonitor::onDisconnected);
connect(mqttClient, &QMqttClient::messageReceived, this, &SmartTrashMonitor::onMessageReceived);
// 初始化UI
setupUI();
// 连接MQTT
mqttClient->connectToHost();
// 初始化数据
fillLevel = 0;
lidStatus = false;
dropCount = 0;
lastUpdate = QDateTime::currentDateTime();
}
private slots:
void onConnected() {
statusBar()->showMessage("已连接到华为云物联网平台", 5000);
mqttClient->subscribe("trashbin/status/data");
}
void onDisconnected() {
statusBar()->showMessage("与物联网平台断开连接", 5000);
}
void onMessageReceived(const QByteArray &message, const QMqttTopicName &topic) {
QJsonParseError parseError;
QJsonDocument doc = QJsonDocument::fromJson(message, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "JSON解析错误:" << parseError.errorString();
return;
}
QJsonObject json = doc.object();
fillLevel = json["fill_level"].toInt();
lidStatus = json["lid_open"].toBool();
dropCount = json["drop_count"].toInt();
lastUpdate = QDateTime::currentDateTime();
updateUI();
}
void openLid() {
if (mqttClient->state() == QMqttClient::Connected) {
QMqttTopicName topic("trashbin/control");
QJsonObject json;
json["command"] = "open_lid";
QJsonDocument doc(json);
mqttClient->publish(topic, doc.toJson());
}
}
void closeLid() {
if (mqttClient->state() == QMqttClient::Connected) {
QMqttTopicName topic("trashbin/control");
QJsonObject json;
json["command"] = "close_lid";
QJsonDocument doc(json);
mqttClient->publish(topic, doc.toJson());
}
}
void updateHistoryChart() {
// 模拟数据更新
static int counter = 0;
series->append(counter, fillLevel);
if (counter > 50) {
axisX->setMin(counter - 50);
axisX->setMax(counter);
}
counter++;
}
private:
void setupUI() {
// 设置窗口属性
setWindowTitle("智能垃圾桶监控系统");
setMinimumSize(800, 600);
// 主布局
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
QHBoxLayout *mainLayout = new QHBoxLayout(centralWidget);
// 左侧面板 - 状态信息
QWidget *leftPanel = new QWidget;
QVBoxLayout *leftLayout = new QVBoxLayout(leftPanel);
// 垃圾桶状态组
QGroupBox *statusGroup = new QGroupBox("垃圾桶状态");
QGridLayout *statusLayout = new QGridLayout(statusGroup);
QLabel *fillLabel = new QLabel("填充状态:");
fillProgress = new QProgressBar;
fillProgress->setRange(0, 100);
fillProgress->setTextVisible(true);
fillProgress->setFormat("%p%");
QLabel *lidLabel = new QLabel("桶盖状态:");
lidStatusLabel = new QLabel("关闭");
lidStatusLabel->setStyleSheet("QLabel { color: green; font-weight: bold; }");
QLabel *countLabel = new QLabel("投放次数:");
dropCountLabel = new QLabel("0");
QLabel *lastUpdateLabel = new QLabel("最后更新时间:");
lastUpdateValue = new QLabel("尚未更新");
statusLayout->addWidget(fillLabel, 0, 0);
statusLayout->addWidget(fillProgress, 0, 1);
statusLayout->addWidget(lidLabel, 1, 0);
statusLayout->addWidget(lidStatusLabel, 1, 1);
statusLayout->addWidget(countLabel, 2, 0);
statusLayout->addWidget(dropCountLabel, 2, 1);
statusLayout->addWidget(lastUpdateLabel, 3, 0);
statusLayout->addWidget(lastUpdateValue, 3, 1);
// 桶盖控制组
QGroupBox *controlGroup = new QGroupBox("桶盖控制");
QHBoxLayout *controlLayout = new QHBoxLayout(controlGroup);
QPushButton *openButton = new QPushButton("打开桶盖");
QPushButton *closeButton = new QPushButton("关闭桶盖");
connect(openButton, &QPushButton::clicked, this, &SmartTrashMonitor::openLid);
connect(closeButton, &QPushButton::clicked, this, &SmartTrashMonitor::closeLid);
controlLayout->addWidget(openButton);
controlLayout->addWidget(closeButton);
// 添加到左侧布局
leftLayout->addWidget(statusGroup);
leftLayout->addWidget(controlGroup);
leftLayout->addStretch();
// 右侧面板 - 图表
QWidget *rightPanel = new QWidget;
QVBoxLayout *rightLayout = new QVBoxLayout(rightPanel);
QGroupBox *chartGroup = new QGroupBox("填充历史趋势");
QVBoxLayout *chartLayout = new QVBoxLayout(chartGroup);
// 创建图表
chart = new QChart;
chart->setTitle("垃圾桶填充量历史数据");
chart->legend()->hide();
series = new QLineSeries;
chart->addSeries(series);
axisX = new QValueAxis;
axisX->setRange(0, 50);
axisX->setLabelFormat("%d");
axisX->setTitleText("时间");
axisY = new QValueAxis;
axisY->setRange(0, 100);
axisY->setTitleText("填充量 (%)");
chart->addAxis(axisX, Qt::AlignBottom);
chart->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisX);
series->attachAxis(axisY);
chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
chartLayout->addWidget(chartView);
rightLayout->addWidget(chartGroup);
// 添加到主布局
mainLayout->addWidget(leftPanel, 1);
mainLayout->addWidget(rightPanel, 2);
// 状态栏
statusBar()->showMessage("正在连接华为云物联网平台...");
// 图表更新定时器
QTimer *chartTimer = new QTimer(this);
connect(chartTimer, &QTimer::timeout, this, &SmartTrashMonitor::updateHistoryChart);
chartTimer->start(2000);
}
void updateUI() {
fillProgress->setValue(fillLevel);
if (lidStatus) {
lidStatusLabel->setText("打开");
lidStatusLabel->setStyleSheet("QLabel { color: red; font-weight: bold; }");
} else {
lidStatusLabel->setText("关闭");
lidStatusLabel->setStyleSheet("QLabel { color: green; font-weight: bold; }");
}
dropCountLabel->setText(QString::number(dropCount));
lastUpdateValue->setText(lastUpdate.toString("yyyy-MM-dd hh:mm:ss"));
statusBar()->showMessage("数据已更新", 3000);
}
private:
QMqttClient *mqttClient;
// UI元素
QProgressBar *fillProgress;
QLabel *lidStatusLabel;
QLabel *dropCountLabel;
QLabel *lastUpdateValue;
// 图表元素
QChart *chart;
QChartView *chartView;
QLineSeries *series;
QValueAxis *axisX;
QValueAxis *axisY;
// 数据
int fillLevel;
bool lidStatus;
int dropCount;
QDateTime lastUpdate;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 设置应用样式
QApplication::setStyle("Fusion");
// 设置调色板
QPalette palette;
palette.setColor(QPalette::Window, QColor(240, 245, 249));
palette.setColor(QPalette::WindowText, QColor(53, 53, 53));
palette.setColor(QPalette::Base, QColor(255, 255, 255));
palette.setColor(QPalette::AlternateBase, QColor(240, 240, 240));
palette.setColor(QPalette::Button, QColor(64, 158, 255));
palette.setColor(QPalette::ButtonText, QColor(255, 255, 255));
palette.setColor(QPalette::Highlight, QColor(64, 158, 255));
palette.setColor(QPalette::HighlightedText, Qt::white);
app.setPalette(palette);
SmartTrashMonitor monitor;
monitor.show();
return app.exec();
}
#include "main.moc"
上位机程序功能说明
这个Qt上位机程序实现了以下功能:
-
MQTT通信:
- 连接到华为云物联网平台
- 订阅垃圾桶状态主题(
trashbin/status/data
) - 发布控制命令(
trashbin/control
)
-
用户界面:
- 实时显示垃圾桶填充状态(进度条)
- 显示桶盖开闭状态(文本指示)
- 显示投放次数统计
- 显示最后更新时间
- 桶盖控制按钮(打开/关闭)
-
数据可视化:
- 填充量历史趋势图表
- 实时更新图表数据
-
状态监控:
- 状态栏显示连接状态
- 实时更新数据接收状态
使用说明
-
需要安装Qt 5.12或更高版本,并包含Qt Charts和Qt MQTT模块
-
在华为云物联网平台创建产品及设备,获取连接参数
-
替换代码中的MQTT连接信息:
your_huawei_iot_host
device_username
device_password
-
编译运行程序,连接成功后即可监控垃圾桶状态
界面特点
- 现代化UI设计,采用蓝白色调
- 响应式布局,适应不同窗口大小
- 直观的状态指示(颜色区分)
- 实时数据图表展示
- 简洁的控制界面
该上位机程序与STM32垃圾桶硬件配合使用,实现了完整的垃圾桶状态监控与远程控制功能。
模块代码设计
设备端模块代码设计(STM32F103C8T6寄存器开发)
#include "stm32f10x.h"
// 硬件引脚定义
#define TRIG_PIN GPIO_Pin_1 // PA1(超声波Trig)
#define ECHO_PIN GPIO_Pin_2 // PA2(超声波Echo)
#define IR_PIN GPIO_Pin_3 // PA3(红外对管)
#define SERVO_PIN GPIO_Pin_6 // PA6(舵机PWM)
#define OLED_CS GPIO_Pin_4 // PA4(OLED片选)
#define OLED_DC GPIO_Pin_5 // PA5(OLED数据/命令)
#define OLED_RES GPIO_Pin_7 // PA7(OLED复位)
// 全局变量
volatile uint8_t lid_open = 0; // 开盖状态
volatile uint16_t drop_count = 0; // 投放次数
volatile float distance_cm = 0; // 超声波距离
volatile uint8_t full_status = 0; // 满溢状态(0:未满 1:已满)
// 延时函数
void Delay_ms(uint32_t ms) {
for(uint32_t i=0; i<ms*8000; i++);
}
// GPIO初始化
void GPIO_Config(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // 使能PORTA时钟
// 超声波TRIG(输出)
GPIOA->CRL &= ~(0xF << 4); // PA1推挽输出
GPIOA->CRL |= (0x03 << 4);
// 红外对管(输入)
GPIOA->CRL &= ~(0xF << 12); // PA3浮空输入
GPIOA->CRL |= (0x04 << 12);
// 舵机PWM(复用输出)
GPIOA->CRL &= ~(0xF << 24); // PA6复用推挽
GPIOA->CRL |= (0x0B << 24);
}
// 定时器3初始化(舵机PWM)
void TIM3_PWM_Init(void) {
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // 使能TIM3时钟
TIM3->ARR = 19999; // 20ms周期(72MHz/72=1MHz)
TIM3->PSC = 71;
TIM3->CCMR1 |= 0x60; // PWM模式1
TIM3->CCER |= TIM_CCER_CC1E; // 通道1使能
TIM3->CR1 |= TIM_CR1_CEN; // 启动定时器
// 初始位置(0°)
TIM3->CCR1 = 500; // 0.5ms脉冲
}
// 舵机控制函数(0°-180°)
void Servo_Control(uint8_t angle) {
uint16_t pulse = 500 + angle * 10; // 500-2500us
TIM3->CCR1 = pulse;
}
// 超声波初始化
void HC_SR04_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // 使能AFIO
// 配置TIM2通道1输入捕获(ECHO)
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
TIM2->PSC = 71; // 1MHz计数
TIM2->CCMR1 |= 0x01; // CC1通道输入模式
TIM2->CCER |= TIM_CCER_CC1E; // 使能捕获
}
// 超声波测距
float Ultrasonic_Measure(void) {
GPIOA->BSRR = TRIG_PIN; // TRIG高电平
Delay_ms(10); // 持续10ms
GPIOA->BRR = TRIG_PIN; // TRIG低电平
TIM2->CR1 |= TIM_CR1_CEN; // 启动定时器
while(!(TIM2->SR & TIM_SR_CC1IF)); // 等待捕获
uint32_t start = TIM2->CCR1;
while(TIM2->SR & TIM_SR_CC1IF); // 清除标志
while(!(TIM2->SR & TIM_SR_CC1IF)); // 等待第二次捕获
uint32_t end = TIM2->CCR1;
TIM2->CR1 &= ~TIM_CR1_CEN; // 停止定时器
TIM2->CNT = 0; // 计数器归零
float time_us = (end > start) ? (end - start) : (0xFFFF - start + end);
return time_us / 58.0; // 转换为cm
}
// 红外检测初始化(外部中断)
void IR_Init(void) {
EXTI->IMR |= EXTI_IMR_MR3; // 使能EXTI3
EXTI->RTSR |= EXTI_RTSR_TR3; // 上升沿触发
AFIO->EXTICR[0] |= 0x0000; // PA3作为EXTI3
NVIC_EnableIRQ(EXTI3_IRQn); // 使能中断
}
// EXTI3中断处理
void EXTI3_IRQHandler(void) {
if(EXTI->PR & EXTI_PR_PR3) {
lid_open = !lid_open; // 切换开盖状态
if(lid_open) drop_count++;// 开盖时计数
EXTI->PR = EXTI_PR_PR3; // 清除中断标志
}
}
// SPI初始化(OLED)
void SPI_Config(void) {
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1; // 主机模式,18MHz
SPI1->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI; // 软件NSS
SPI1->CR1 |= SPI_CR1_SPE; // 使能SPI
}
// OLED写命令
void OLED_WriteCmd(uint8_t cmd) {
GPIOA->BRR = OLED_DC; // DC=0(命令)
GPIOA->BRR = OLED_CS; // CS=0
SPI1->DR = cmd; // 发送命令
while(!(SPI1->SR & SPI_SR_TXE)); // 等待发送完成
GPIOA->BSRR = OLED_CS; // CS=1
}
// OLED写数据
void OLED_WriteData(uint8_t dat) {
GPIOA->BSRR = OLED_DC; // DC=1(数据)
GPIOA->BRR = OLED_CS; // CS=0
SPI1->DR = dat; // 发送数据
while(!(SPI1->SR & SPI_SR_TXE)); // 等待发送完成
GPIOA->BSRR = OLED_CS; // CS=1
}
// OLED显示状态
void OLED_DisplayStatus(void) {
// 显示标题
OLED_WriteCmd(0x80);
const char title[] = "Smart Bin";
for(uint8_t i=0; i<sizeof(title)-1; i++)
OLED_WriteData(title[i]);
// 显示开盖状态
OLED_WriteCmd(0xC0);
const char lid[] = "Lid: ";
for(uint8_t i=0; i<sizeof(lid)-1; i++)
OLED_WriteData(lid[i]);
OLED_WriteData(lid_open ? 'O' : 'C');
// 显示满溢状态
OLED_WriteCmd(0xD0);
const char full[] = "Full: ";
for(uint8_t i=0; i<sizeof(full)-1; i++)
OLED_WriteData(full[i]);
OLED_WriteData(full_status ? 'Y' : 'N');
// 显示投放次数
OLED_WriteCmd(0xE0);
const char drop[] = "Drops: ";
for(uint8_t i=0; i<sizeof(drop)-1; i++)
OLED_WriteData(drop[i]);
OLED_WriteData(drop_count/100 + '0');
OLED_WriteData((drop_count%100)/10 + '0');
OLED_WriteData(drop_count%10 + '0');
}
// ESP8266初始化(USART1)
void ESP8266_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// PA9(TX)复用推挽, PA10(RX)浮空输入
GPIOA->CRH &= ~(0xFF << 4);
GPIOA->CRH |= (0x0B << 4) | (0x04 << 8);
USART1->BRR = 72000000 / 115200; // 波特率115200
USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}
// ESP8266发送数据
void ESP8266_Send(const char *data) {
while(*data) {
USART1->DR = *data++;
while(!(USART1->SR & USART_SR_TXE));
}
}
// 上传数据到华为云
void Upload_To_HuaweiCloud(void) {
char buffer[64];
sprintf(buffer, "AT+MQTTPUB=0,\"topic/status\",\"%d,%d,%.1f,%d\"\r\n",
lid_open, full_status, distance_cm, drop_count);
ESP8266_Send(buffer);
}
int main(void) {
// 系统初始化
SystemInit();
GPIO_Config();
TIM3_PWM_Init();
HC_SR04_Init();
IR_Init();
SPI_Config();
ESP8266_Init();
// OLED初始化
GPIOA->BSRR = OLED_RES; // 复位OLED
Delay_ms(100);
GPIOA->BRR = OLED_RES;
Delay_ms(100);
// OLED初始化序列(省略)
while(1) {
// 1. 检测满溢状态
distance_cm = Ultrasonic_Measure();
full_status = (distance_cm < 10.0) ? 1 : 0; // 距离<10cm为满
// 2. 自动开盖控制
if(GPIOA->IDR & IR_PIN) { // 检测到人体
Servo_Control(90); // 开盖90°
Delay_ms(5000); // 保持5秒
Servo_Control(0); // 关盖
}
// 3. OLED显示
OLED_DisplayStatus();
// 4. 上传数据到云平台
Upload_To_HuaweiCloud();
Delay_ms(2000); // 每2秒更新一次
}
}
关键模块说明
-
超声波测距模块(HC-SR04)
- 使用TIM2输入捕获测量高电平时间
- 计算公式:距离 = 高电平时间(us) / 58
-
红外检测模块
- 使用外部中断(EXTI)检测开盖动作
- 上升沿触发中断,记录投放次数
-
舵机控制模块(SG90)
- TIM3产生PWM信号控制舵机
- 0.5ms脉冲(0°) ~ 2.5ms脉冲(180°)
-
OLED显示模块
- SPI接口驱动0.96寸OLED
- 实时显示开盖状态/满溢状态/投放次数
-
WiFi通信模块(ESP8266)
- USART1实现AT指令通信
- MQTT协议上传数据到华为云
-
主控逻辑
- 每2秒更新一次传感器数据
- 自动开盖通过红外触发
- 满溢判断阈值:10cm
项目核心代码
#include "stm32f10x.h"
#include "oled.h"
#include "ultrasonic.h"
#include "infrared.h"
#include "servo.h"
#include "esp8266.h"
#include "delay.h"
// 宏定义
#define FULL_THRESHOLD 15 // 满溢距离阈值(单位:cm)
#define COVER_OPEN_ANGLE 90 // 开盖角度
#define COVER_CLOSE_ANGLE 0 // 关盖角度
#define AUTO_CLOSE_DELAY 3000 // 自动关盖延时(ms)
#define UPLOAD_INTERVAL 5000 // 数据上传间隔(ms)
// 全局状态变量
volatile uint8_t cover_state = 0; // 桶盖状态 0:关闭 1:打开
volatile uint8_t full_state = 0; // 满溢状态 0:未满 1:已满
volatile uint16_t drop_count = 0; // 投放次数计数
volatile uint32_t last_upload = 0; // 上次上传时间戳
// 函数声明
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void TIM2_Configuration(void);
void update_display(void);
void upload_to_cloud(void);
int main(void)
{
// 初始化系统
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
TIM2_Configuration();
Delay_Init();
OLED_Init();
Ultrasonic_Init();
Infrared_Init();
Servo_Init();
ESP8266_Init();
// 初始状态设置
Servo_SetAngle(COVER_CLOSE_ANGLE);
OLED_Clear();
while(1)
{
// 1. 满溢状态检测
float distance = Ultrasonic_Measure();
full_state = (distance < FULL_THRESHOLD) ? 1 : 0;
// 2. 开盖检测与自动控制
if(Infrared_Detect()) // 检测到人体
{
if(!cover_state) // 如果当前是关闭状态
{
cover_state = 1;
drop_count++; // 增加投放计数
Servo_SetAngle(COVER_OPEN_ANGLE);
}
last_detect_time = Get_SystemTick(); // 重置自动关盖计时
}
// 3. 自动关盖检测
if(cover_state && (Get_SystemTick() - last_detect_time > AUTO_CLOSE_DELAY))
{
cover_state = 0;
Servo_SetAngle(COVER_CLOSE_ANGLE);
}
// 4. OLED状态显示
update_display();
// 5. 定时上传数据到云平台
if(Get_SystemTick() - last_upload > UPLOAD_INTERVAL)
{
upload_to_cloud();
last_upload = Get_SystemTick();
}
Delay_Ms(100); // 主循环延时
}
}
// 更新OLED显示
void update_display(void)
{
OLED_ShowString(0, 0, "Cover:");
OLED_ShowString(0, 2, "Full :");
OLED_ShowString(0, 4, "Count:");
// 显示开盖状态
if(cover_state) OLED_ShowString(60, 0, "OPEN ");
else OLED_ShowString(60, 0, "CLOSE");
// 显示满溢状态
if(full_state) OLED_ShowString(60, 2, "YES ");
else OLED_ShowString(60, 2, "NO ");
// 显示投放次数
OLED_ShowNum(60, 4, drop_count, 5);
}
// 上传数据到华为云
void upload_to_cloud(void)
{
char buffer[64];
// 组装JSON数据
sprintf(buffer, "{\"cover\":%d,\"full\":%d,\"count\":%d}",
cover_state, full_state, drop_count);
// 通过ESP8266发送数据
ESP8266_SendData(buffer);
}
// 系统时钟配置
void RCC_Configuration(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
}
// GPIO初始化
void GPIO_Configuration(void)
{
// 配置超声波模块引脚
GPIOA->CRH &= 0xFFFFF00F;
GPIOA->CRH |= 0x00000330; // PA11推挽输出, PA12浮空输入
// 红外模块输入
GPIOB->CRL &= 0xFF0FFFFF;
GPIOB->CRL |= 0x00800000; // PB5浮空输入
}
// 中断配置
void NVIC_Configuration(void)
{
NVIC_EnableIRQ(TIM2_IRQn);
NVIC_SetPriority(TIM2_IRQn, 0);
}
// 定时器2配置(用于舵机PWM)
void TIM2_Configuration(void)
{
TIM2->PSC = 72 - 1; // 预分频 1MHz
TIM2->ARR = 20000 - 1; // 重载值(20ms周期)
TIM2->CCR1 = 1500; // 初始占空比(1.5ms)
TIM2->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // PWM模式
TIM2->CCER |= TIM_CCER_CC1E; // 使能通道1
TIM2->CR1 |= TIM_CR1_CEN; // 启动定时器
}
// 定时器2中断服务函数
void TIM2_IRQHandler(void)
{
if(TIM2->SR & TIM_SR_UIF)
{
TIM2->SR &= ~TIM_SR_UIF;
// 超声波定时处理
Ultrasonic_TIM_IRQ();
}
}
代码说明:
-
系统初始化:
- 配置系统时钟、GPIO、中断和定时器
- 初始化所有外设模块(OLED、超声波、红外、舵机、WiFi)
-
主要功能实现:
- 满溢检测: 超声波模块实时测量距离,低于阈值触发满溢状态
- 自动开盖: 检测到人体时控制舵机开盖并记录投放次数
- 自动关盖: 开盖后3秒无操作自动关闭
- 状态显示: OLED实时显示桶盖状态/满溢状态/投放次数
- 数据上传: 每5秒通过ESP8266上传JSON格式数据到华为云
-
关键模块接口:
Ultrasonic_Measure()
:获取超声波距离测量值Infrared_Detect()
:检测人体接近信号Servo_SetAngle()
:控制舵机角度ESP8266_SendData()
:发送数据到云平台Get_SystemTick()
:获取系统运行时间(ms)
-
寄存器操作:
- 直接操作STM32寄存器配置时钟/GPIO/定时器
- 使用TIM2生成舵机控制所需的PWM信号
- 通过中断处理超声波模块的时序控制
总结
本文设计并实现了一款基于STM32F103C8T6的智能垃圾桶监控系统,综合运用多传感器技术与物联网平台,实现了垃圾桶管理的智能化与远程化。系统通过红外对管精准检测开盖状态并统计投放次数,结合超声波模块实时监测垃圾桶满溢程度,利用SG90舵机实现红外感应自动开盖功能,显著提升了用户体验。本地0.96寸SPI OLED屏幕直观显示桶内状态、开盖次数等关键数据,便于用户现场查看。
通过ESP8266 WiFi模块将采集的桶满状态、开盖记录等数据实时上传至华为云物联网平台,构建了完整的数据链路。用户可通过Qt开发的Android APP或PC端程序远程监控垃圾桶状态,实现跨平台管理。系统采用DC 5V供电配合AMS1117稳压模块,确保各硬件模块稳定运行。
该设计将传统垃圾桶升级为具备状态感知、自动控制、数据可视化和云端交互能力的智能终端,为城市环卫管理、智能家居等场景提供了高效解决方案。其模块化架构兼顾功能完备性与成本控制,具有较高的实用价值和推广潜力。
- 点赞
- 收藏
- 关注作者
评论(0)