基于STM32的智能垃圾桶监控系统设计

举报
DS小龙哥 发表于 2025/06/22 18:41:29 2025/06/22
【摘要】 项目开发背景 项目开发背景随着城市化进程加速和人口密度不断提高,生活垃圾产量持续增长,传统垃圾桶管理面临严峻挑战。人工巡查方式效率低下、响应滞后,常出现垃圾满溢未及时清理的情况,不仅影响环境卫生,滋生蚊虫细菌,还可能因异味扩散引发居民投诉,增加城市管理成本。同时,垃圾分类政策的推行也对垃圾桶状态监控提出了更高要求。物联网(IoT)和嵌入式技术的快速发展为解决上述问题提供了新思路。通过将感知...

项目开发背景

项目开发背景

随着城市化进程加速和人口密度不断提高,生活垃圾产量持续增长,传统垃圾桶管理面临严峻挑战。人工巡查方式效率低下、响应滞后,常出现垃圾满溢未及时清理的情况,不仅影响环境卫生,滋生蚊虫细菌,还可能因异味扩散引发居民投诉,增加城市管理成本。同时,垃圾分类政策的推行也对垃圾桶状态监控提出了更高要求。

物联网(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.96SPI OLED                |         
|                     |  CS: PA4, SCK: PA5, MOSI: PA7      |         
|                     |  DC: PB0, RES: PB1                 |         
|                     | (本地显示状态/报警信息)             |         
|                     +------------------------------------+         
+--------------------------------------------------------------------+
|                           供电层(能源管理)                         |
|                     +------------------------------------+         |
|                     |  DC 5V输入 → AMS1117稳压模块       |         |
|                     |  输出: 3.3V (主控/传感器)           |         |
|                     |       5V (舵机直接供电)             |         |
|                     +------------------------------------+         |
+--------------------------------------------------------------------+

框架说明:

  1. 应用层
    • Qt开发的APP通过华为云平台获取实时数据
  2. 网络层
    • ESP8266通过UART与STM32通信,使用MQTT协议上传数据
  3. 控制层
    • STM32协调所有模块:
      • 超声波测距判断满溢(PA1/PA2)
      • 红外对管检测开盖状态(PA0)
      • 舵机控制自动开盖(PA3-PWM)
      • OLED显示实时状态(SPI接口)
  4. 供电层
    • 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上位机程序实现了以下功能:

  1. MQTT通信

    • 连接到华为云物联网平台
    • 订阅垃圾桶状态主题(trashbin/status/data)
    • 发布控制命令(trashbin/control)
  2. 用户界面

    • 实时显示垃圾桶填充状态(进度条)
    • 显示桶盖开闭状态(文本指示)
    • 显示投放次数统计
    • 显示最后更新时间
    • 桶盖控制按钮(打开/关闭)
  3. 数据可视化

    • 填充量历史趋势图表
    • 实时更新图表数据
  4. 状态监控

    • 状态栏显示连接状态
    • 实时更新数据接收状态

使用说明

  1. 需要安装Qt 5.12或更高版本,并包含Qt Charts和Qt MQTT模块

  2. 在华为云物联网平台创建产品及设备,获取连接参数

  3. 替换代码中的MQTT连接信息:

    • your_huawei_iot_host
    • device_username
    • device_password
  4. 编译运行程序,连接成功后即可监控垃圾桶状态

界面特点

  • 现代化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秒更新一次
    }
}

关键模块说明

  1. 超声波测距模块(HC-SR04)

    • 使用TIM2输入捕获测量高电平时间
    • 计算公式:距离 = 高电平时间(us) / 58
  2. 红外检测模块

    • 使用外部中断(EXTI)检测开盖动作
    • 上升沿触发中断,记录投放次数
  3. 舵机控制模块(SG90)

    • TIM3产生PWM信号控制舵机
    • 0.5ms脉冲(0°) ~ 2.5ms脉冲(180°)
  4. OLED显示模块

    • SPI接口驱动0.96寸OLED
    • 实时显示开盖状态/满溢状态/投放次数
  5. WiFi通信模块(ESP8266)

    • USART1实现AT指令通信
    • MQTT协议上传数据到华为云
  6. 主控逻辑

    • 每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();
    }
}

代码说明:

  1. 系统初始化:

    • 配置系统时钟、GPIO、中断和定时器
    • 初始化所有外设模块(OLED、超声波、红外、舵机、WiFi)
  2. 主要功能实现:

    • 满溢检测: 超声波模块实时测量距离,低于阈值触发满溢状态
    • 自动开盖: 检测到人体时控制舵机开盖并记录投放次数
    • 自动关盖: 开盖后3秒无操作自动关闭
    • 状态显示: OLED实时显示桶盖状态/满溢状态/投放次数
    • 数据上传: 每5秒通过ESP8266上传JSON格式数据到华为云
  3. 关键模块接口:

    • Ultrasonic_Measure():获取超声波距离测量值
    • Infrared_Detect():检测人体接近信号
    • Servo_SetAngle():控制舵机角度
    • ESP8266_SendData():发送数据到云平台
    • Get_SystemTick():获取系统运行时间(ms)
  4. 寄存器操作:

    • 直接操作STM32寄存器配置时钟/GPIO/定时器
    • 使用TIM2生成舵机控制所需的PWM信号
    • 通过中断处理超声波模块的时序控制

总结

本文设计并实现了一款基于STM32F103C8T6的智能垃圾桶监控系统,综合运用多传感器技术与物联网平台,实现了垃圾桶管理的智能化与远程化。系统通过红外对管精准检测开盖状态并统计投放次数,结合超声波模块实时监测垃圾桶满溢程度,利用SG90舵机实现红外感应自动开盖功能,显著提升了用户体验。本地0.96寸SPI OLED屏幕直观显示桶内状态、开盖次数等关键数据,便于用户现场查看。

通过ESP8266 WiFi模块将采集的桶满状态、开盖记录等数据实时上传至华为云物联网平台,构建了完整的数据链路。用户可通过Qt开发的Android APP或PC端程序远程监控垃圾桶状态,实现跨平台管理。系统采用DC 5V供电配合AMS1117稳压模块,确保各硬件模块稳定运行。

该设计将传统垃圾桶升级为具备状态感知、自动控制、数据可视化和云端交互能力的智能终端,为城市环卫管理、智能家居等场景提供了高效解决方案。其模块化架构兼顾功能完备性与成本控制,具有较高的实用价值和推广潜力。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。