基于STM32F103C8T6与华为云的智能楼宇照明控制系统设计
项目开发背景
随着城市化进程的加速和建筑行业的快速发展,智能楼宇系统已成为现代建筑管理的重要组成部分。照明系统作为楼宇能耗的主要来源之一,其智能化控制对于提升能源效率、降低运营成本以及增强用户体验具有至关重要的意义。传统照明系统往往依赖于手动开关或简单的定时控制,无法根据实际环境光照和人员活动情况进行动态调整,导致能源浪费和照明效果不佳。因此,开发一种基于先进传感技术和物联网平台的智能照明控制系统,成为当前楼宇自动化领域的热点需求。
在能源紧缺和环境保护日益受到重视的背景下,智能照明系统通过集成光照传感器和人体感应器,能够实时监测各区域的环境状态,并自动调节照明设备的开关与亮度,从而显著减少不必要的能耗。此外,借助云平台实现数据上传和远程监控,可以进一步提升系统的智能化水平,为楼宇管理者提供数据支持和决策依据。华为云物联网平台作为可靠的云服务解决方案,能够高效处理设备数据,并支持远程控制和历史数据分析,满足现代楼宇对实时性和可靠性的要求。
本项目以STM32F103C8T6微控制器为核心,结合GY-30光照传感器、HC-SR501人体红外传感器等硬件组件,构建了一个低成本、高效率的智能照明控制系统。通过ESP8266-01S Wi-Fi模块将采集到的照明状态和能耗数据上传至华为云,并利用QT开发的上位机实现远程手动控制和数据可视化,该系统不仅提升了照明的自适应能力,还为楼宇节能和智能化管理提供了实用化的解决方案。这一设计顺应了物联网和智能建筑的发展趋势,具有广泛的应用前景和社会价值。
设计实现的功能
(1)实时监测各区域光照强度及人体存在状态。
(2)根据环境光照和人员活动自动控制LED照明灯的开关与亮度。
(3)照明状态数据及能耗数据上传至华为云物联网平台。
(4)QT上位机可远程手动控制各区域照明,并显示照明状态历史数据曲线。
项目硬件模块组成
(1)STM32F103C8T6最小系统核心板
(2)GY-30光照强度传感器
(3)HC-SR501人体红外传感器
(4)LED照明灯组与LM2596降压模块
(5)ESP8266-01S Wi-Fi模块
(6)洞洞板焊接所有外围电路,杜邦线连接各传感器模块
设计意义
本设计通过实时监测各区域光照强度及人体存在状态,实现了照明系统的智能化控制,有效避免了无人区域照明浪费,显著降低楼宇照明能耗,从而促进能源节约和环境保护。自动调节照明亮度不仅提升了用户体验,还减少了电费支出,符合绿色建筑和可持续发展的理念。
借助华为云物联网平台,系统能够上传照明状态和能耗数据,实现远程监控和数据分析,为楼宇管理提供数据支持。这使得管理人员可以实时了解照明使用情况,进行趋势分析和优化决策,提高管理效率。
QT上位机的远程手动控制功能增强了系统的灵活性和可操作性,允许用户根据需要调整照明状态,并查看历史数据曲线,便于故障排查和性能评估。这种集成提升了楼宇智能化的整体水平,为未来智慧城市的发展奠定了基础。
设计思路
系统设计以STM32F103C8T6最小系统核心板作为主控制器,负责协调整个智能照明控制系统的运行。该系统通过集成GY-30光照强度传感器和HC-SR501人体红外传感器,实时采集各区域的环境光照数据和人员活动状态。采集到的数据经过STM32处理,用于实现自动控制逻辑,确保照明系统能够根据实际环境条件做出响应。
数据采集部分,GY-30传感器通过I2C接口与STM32通信,提供精确的光照强度值;HC-SR501传感器则输出数字信号指示人体存在。STM32定期读取这些传感器数据,并进行滤波和阈值判断,以确定是否需要调整照明状态。控制输出通过PWM信号驱动LED照明灯组,结合LM2596降压模块实现调光功能,从而根据光照不足和人员活动自动开关或调节亮度,达到节能目的。
通信模块采用ESP8266-01S Wi-Fi模块,STM32通过串口与ESP8266交互,将处理后的照明状态数据、能耗数据等通过MQTT协议上传至华为云物联网平台。这一过程确保了数据的实时性和可靠性,同时支持远程监控。华为云平台作为数据中转站,存储历史数据并支持QT上位机的访问。
QT上位机应用程序通过华为云API获取照明状态和能耗数据,实现远程手动控制各区域照明开关及亮度调节。上位机界面设计包括实时数据显示和历史数据曲线绘制,方便用户查看趋势和分析能耗。整个系统硬件通过洞洞板焊接外围电路,并使用杜邦线连接各模块,确保结构紧凑且易于调试。
框架图
+---------------------+ +-----------------------+
| GY-30 Light Sensor |---I2C-->| |
| | | STM32F103C8T6 |
+---------------------+ | Main Controller |
+---------------------+ | |
| HC-SR501 PIR Sensor |---GPIO-->| |
| | +-----------------------+
+---------------------+ |
| PWM
v
+---------------------+
| LED Light Group |
| with LM2596 & PWM |
+---------------------+
|
| UART
v
+---------------------+
| ESP8266-01S |
| Wi-Fi Module |
+---------------------+
|
| Wi-Fi
v
+---------------------+
| Huawei Cloud IoT |
| Platform |
+---------------------+
|
| Internet
v
+---------------------+
| QT Upper Computer |
| (Remote Control & |
| Data Display) |
+---------------------+
系统总体设计
本系统以STM32F103C8T6最小系统核心板作为主控制器,负责协调整个智能楼宇照明控制系统的运行。系统通过GY-30光照强度传感器实时采集各区域的环境光照数据,同时利用HC-SR501人体红外传感器检测人员活动状态,确保对光照和人体存在的监测准确性。这些传感器数据通过杜邦线连接至STM32控制器,由内置ADC和GPIO接口进行采集和处理。
控制逻辑基于采集到的环境光照和人员活动数据自动执行,STM32通过PWM输出控制LED照明灯组的开关与亮度调节,结合LM2596降压模块实现稳定的调光功能。当环境光照不足且检测到人员存在时,系统会自动开启LED灯并调整至合适亮度;反之则关闭或降低亮度,以达到节能和智能照明的目的。
数据上传部分通过ESP8266-01S Wi-Fi模块实现,该模块连接到本地Wi-Fi网络,并与华为云物联网平台建立通信连接。STM32将处理后的照明状态数据及能耗数据封装为MQTT协议格式,通过串口发送至ESP8266模块,进而上传至云平台,实现远程数据存储和监控。
QT上位机应用程序作为远程控制界面,允许用户手动控制各区域照明开关和亮度,并通过图表形式显示照明状态的历史数据曲线。上位机通过云平台API获取数据,实现与硬件系统的交互,为用户提供直观的操作和数据分析体验。整个系统的外围电路基于洞洞板焊接完成,确保连接可靠性和实验灵活性。
系统功能总结
功能 | 描述 |
---|---|
实时监测 | 使用GY-30传感器采集各区域光照强度,HC-SR501传感器检测人体存在状态 |
自动控制 | 根据环境光照和人员活动,通过PWM调光自动控制LED照明灯的开关与亮度 |
数据上传 | 通过ESP8266 Wi-Fi模块将照明状态及能耗数据上传至华为云物联网平台 |
远程监控 | QT上位机支持远程手动控制各区域照明,并显示照明状态历史数据曲线 |
设计的各个功能模块描述
主控制模块基于STM32F103C8T6最小系统核心板,作为系统的中央处理单元,负责协调所有外围设备的工作。它通过ADC读取传感器数据,处理逻辑判断,生成PWM信号控制照明输出,并管理Wi-Fi模块的通信任务,确保整个系统高效运行。
光照监测模块采用GY-30光照强度传感器,该传感器通过I2C接口与主控制器连接,实时采集环境光照强度数据。传感器将光信号转换为电信号,并提供数字输出,主控制器据此判断当前光照水平,为自动调光控制提供依据。
人体检测模块使用HC-SR501人体红外传感器,通过检测红外辐射变化来感知人员活动状态。传感器输出数字信号指示人体存在与否,主控制器读取此信号并结合光照数据,决定是否触发照明开关或调整亮度,实现智能控制。
照明控制模块包括LED照明灯组和LM2596降压模块,主控制器通过PWM输出信号调节LED的亮度。LM2596模块提供稳定的电压供应,确保PWM调光平滑有效,从而根据环境需求和人员活动自动控制照明开关及亮度水平。
通信模块依托ESP8266-01S Wi-Fi模块,实现与华为云物联网平台的数据交互。该模块通过串口与主控制器通信,将光照强度、人体状态、照明状态及能耗数据上传至云平台,同时接收来自云端的控制指令,支持远程监控和管理。
上位机模块基于QT开发的可视化界面,允许用户远程手动控制各区域照明,并显示照明状态历史数据曲线。它通过华为云平台获取实时数据,提供图形化交互,方便用户查看趋势和进行手动干预,增强系统的可操作性和数据分析能力。
上位机代码设计
// SmartLightingController.pro
QT += core gui mqtt charts widgets
CONFIG += c++11
SOURCES += main.cpp mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMqttClient>
#include <QChart>
#include <QLineSeries>
#include <QValueAxis>
#include <QChartView>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_connectButton_clicked();
void on_disconnectButton_clicked();
void on_controlButton1_clicked();
void on_controlButton2_clicked();
void on_controlButton3_clicked();
void handleMessage(const QByteArray &message, const QString &topic);
void updateLog(const QString &message);
private:
Ui::MainWindow *ui;
QMqttClient *m_client;
QChart *m_chart;
QLineSeries *m_lightSeries;
QLineSeries *m_energySeries;
QVector<QString> m_timeData;
QVector<double> m_lightData;
QVector<double> m_energyData;
void setupMQTT();
void setupChart();
void publishControl(int area, bool state);
};
#endif // MAINWINDOW_H
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_client(new QMqttClient(this)),
m_chart(new QChart()),
m_lightSeries(new QLineSeries()),
m_energySeries(new QLineSeries())
{
ui->setupUi(this);
setupChart();
setupMQTT();
connect(m_client, &QMqttClient::messageReceived, this, &MainWindow::handleMessage);
connect(m_client, &QMqttClient::connected, this, [this]() { updateLog("Connected to Huawei Cloud IoT"); });
connect(m_client, &QMqttClient::disconnected, this, [this]() { updateLog("Disconnected"); });
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setupChart()
{
m_chart->addSeries(m_lightSeries);
m_chart->addSeries(m_energySeries);
m_chart->setTitle("Lighting Status and Energy Consumption");
m_chart->createDefaultAxes();
m_chart->axes(Qt::Horizontal).first()->setTitleText("Time");
m_chart->axes(Qt::Vertical).first()->setTitleText("Value");
ui->chartView->setChart(m_chart);
}
void MainWindow::setupMQTT()
{
m_client->setHostName("iot-mqtts.cn-north-4.myhuaweicloud.com");
m_client->setPort(1883);
m_client->setUsername("your_product_id/your_device_id");
m_client->setPassword("your_device_secret");
}
void MainWindow::on_connectButton_clicked()
{
if (m_client->state() == QMqttClient::Disconnected) {
m_client->connectToHost();
m_client->subscribe("lighting/data");
} else {
updateLog("Already connected");
}
}
void MainWindow::on_disconnectButton_clicked()
{
if (m_client->state() == QMqttClient::Connected) {
m_client->disconnectFromHost();
}
}
void MainWindow::on_controlButton1_clicked() { publishControl(1, ui->controlButton1->isChecked()); }
void MainWindow::on_controlButton2_clicked() { publishControl(2, ui->controlButton2->isChecked()); }
void MainWindow::on_controlButton3_clicked() { publishControl(3, ui->controlButton3->isChecked()); }
void MainWindow::publishControl(int area, bool state)
{
if (m_client->state() != QMqttClient::Connected) {
updateLog("Not connected. Cannot send control.");
return;
}
QJsonObject controlMsg;
controlMsg["area"] = area;
controlMsg["state"] = state;
QJsonDocument doc(controlMsg);
m_client->publish("lighting/control", doc.toJson());
updateLog(QString("Control sent: Area %1, State %2").arg(area).arg(state ? "ON" : "OFF"));
}
void MainWindow::handleMessage(const QByteArray &message, const QString &topic)
{
QJsonDocument doc = QJsonDocument::fromJson(message);
if (doc.isNull()) {
updateLog("Invalid JSON received");
return;
}
QJsonObject obj = doc.object();
double light = obj["light"].toDouble();
bool human = obj["human"].toBool();
double energy = obj["energy"].toDouble();
QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss");
m_timeData.append(timestamp);
m_lightData.append(light);
m_energyData.append(energy);
m_lightSeries->clear();
m_energySeries->clear();
for (int i = 0; i < m_timeData.size(); ++i) {
m_lightSeries->append(i, m_lightData[i]);
m_energySeries->append(i, m_energyData[i]);
}
m_chart->axes(Qt::Horizontal).first()->setRange(0, m_timeData.size() - 1);
double minVal = qMin(*std::min_element(m_lightData.begin(), m_lightData.end()),
*std::min_element(m_energyData.begin(), m_energyData.end()));
double maxVal = qMax(*std::max_element(m_lightData.begin(), m_lightData.end()),
*std::max_element(m_energyData.begin(), m_energyData.end()));
m_chart->axes(Qt::Vertical).first()->setRange(minVal, maxVal);
ui->statusLabel->setText(QString("Light: %1 lux, Human: %2, Energy: %3 kWh")
.arg(light).arg(human ? "Yes" : "No").arg(energy));
updateLog(QString("Data received: Light=%1, Human=%2, Energy=%3").arg(light).arg(human).arg(energy));
}
void MainWindow::updateLog(const QString &message)
{
ui->logList->addItem(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + " - " + message);
}
// main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
<!-- mainwindow.ui -->
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Smart Lighting Controller</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="controlLayout">
<item>
<widget class="QPushButton" name="connectButton">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="disconnectButton">
<property name="text">
<string>Disconnect</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="controlButton1">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Area 1 OFF</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="controlButton2">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Area 2 OFF</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="controlButton3">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Area 3 OFF</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="text">
<string>Status: Disconnected</string>
</property>
</widget>
</item>
<item>
<widget class="QChartView" name="chartView"/>
</item>
<item>
<widget class="QListWidget" name="logList"/>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
模块代码设计
#include <stdint.h>
// 寄存器地址定义
#define RCC_BASE 0x40021000
#define GPIOA_BASE 0x40010800
#define GPIOB_BASE 0x40010C00
#define I2C1_BASE 0x40005400
#define TIM2_BASE 0x40000000
#define USART2_BASE 0x40004400
// RCC寄存器
#define RCC_APB2ENR (*((volatile uint32_t *)(RCC_BASE + 0x18)))
#define RCC_APB1ENR (*((volatile uint32_t *)(RCC_BASE + 0x1C)))
// GPIO寄存器
#define GPIOA_CRL (*((volatile uint32_t *)(GPIOA_BASE + 0x00)))
#define GPIOA_CRH (*((volatile uint32_t *)(GPIOA_BASE + 0x04)))
#define GPIOA_IDR (*((volatile uint32_t *)(GPIOA_BASE + 0x08)))
#define GPIOA_ODR (*((volatile uint32_t *)(GPIOA_BASE + 0x0C)))
#define GPIOB_CRL (*((volatile uint32_t *)(GPIOB_BASE + 0x00)))
#define GPIOB_CRH (*((volatile uint32_t *)(GPIOB_BASE + 0x04)))
#define GPIOB_ODR (*((volatile uint32_t *)(GPIOB_BASE + 0x0C)))
// I2C1寄存器
#define I2C1_CR1 (*((volatile uint32_t *)(I2C1_BASE + 0x00)))
#define I2C1_CR2 (*((volatile uint32_t *)(I2C1_BASE + 0x04)))
#define I2C1_OAR1 (*((volatile uint32_t *)(I2C1_BASE + 0x08)))
#define I2C1_OAR2 (*((volatile uint32_t *)(I2C1_BASE + 0x0C)))
#define I2C1_DR (*((volatile uint32_t *)(I2C1_BASE + 0x10)))
#define I2C1_SR1 (*((volatile uint32_t *)(I2C1_BASE + 0x14)))
#define I2C1_SR2 (*((volatile uint32_t *)(I2C1_BASE + 0x18)))
#define I2C1_CCR (*((volatile uint32_t *)(I2C1_BASE + 0x1C)))
#define I2C1_TRISE (*((volatile uint32_t *)(I2C1_BASE + 0x20)))
// TIM2寄存器
#define TIM2_CR1 (*((volatile uint32_t *)(TIM2_BASE + 0x00)))
#define TIM2_CR2 (*((volatile uint32_t *)(TIM2_BASE + 0x04)))
#define TIM2_SMCR (*((volatile uint32_t *)(TIM2_BASE + 0x08)))
#define TIM2_DIER (*((volatile uint32_t *)(TIM2_BASE + 0x0C)))
#define TIM2_SR (*((volatile uint32_t *)(TIM2_BASE + 0x10)))
#define TIM2_EGR (*((volatile uint32_t *)(TIM2_BASE + 0x14)))
#define TIM2_CCMR1 (*((volatile uint32_t *)(TIM2_BASE + 0x18)))
#define TIM2_CCMR2 (*((volatile uint32_t *)(TIM2_BASE + 0x1C)))
#define TIM2_CCER (*((volatile uint32_t *)(TIM2_BASE + 0x20)))
#define TIM2_CNT (*((volatile uint32_t *)(TIM2_BASE + 0x24)))
#define TIM2_PSC (*((volatile uint32_t *)(TIM2_BASE + 0x28)))
#define TIM2_ARR (*((volatile uint32_t *)(TIM2_BASE + 0x2C)))
#define TIM2_CCR1 (*((volatile uint32_t *)(TIM2_BASE + 0x34)))
#define TIM2_CCR2 (*((volatile uint32_t *)(TIM2_BASE + 0x38)))
// USART2寄存器
#define USART2_SR (*((volatile uint32_t *)(USART2_BASE + 0x00)))
#define USART2_DR (*((volatile uint32_t *)(USART2_BASE + 0x04)))
#define USART2_BRR (*((volatile uint32_t *)(USART2_BASE + 0x08)))
#define USART2_CR1 (*((volatile uint32_t *)(USART2_BASE + 0x0C)))
#define USART2_CR2 (*((volatile uint32_t *)(USART2_BASE + 0x10)))
#define USART2_CR3 (*((volatile uint32_t *)(USART2_BASE + 0x14)))
// 引脚定义
#define HC_SR501_PIN 0 // PA0 for human sensor input
#define LED_PWM_PIN 1 // PA1 for LED PWM output
#define ESP8266_TX_PIN 2 // PA2 for USART2 TX
#define ESP8266_RX_PIN 3 // PA3 for USART2 RX
#define I2C1_SCL_PIN 6 // PB6 for I2C1 SCL
#define I2C1_SDA_PIN 7 // PB7 for I2C1 SDA
// BH1750地址和命令
#define BH1750_ADDRESS 0x23 // 7-bit address
#define BH1750_POWER_ON 0x01
#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10
// 函数声明
void SystemInit(void);
void GPIO_Init(void);
void I2C1_Init(void);
void I2C1_Start(void);
void I2C1_Stop(void);
void I2C1_Write(uint8_t data);
uint8_t I2C1_Read(uint8_t ack);
void BH1750_Init(void);
uint16_t BH1750_ReadLight(void);
uint8_t Read_HC_SR501(void);
void TIM2_Init(void);
void Set_LED_Brightness(uint16_t brightness);
void USART2_Init(void);
void USART2_SendChar(char ch);
void USART2_SendString(const char *str);
char USART2_ReceiveChar(void);
void Delay_ms(uint32_t ms);
int main(void) {
SystemInit();
GPIO_Init();
I2C1_Init();
BH1750_Init();
TIM2_Init();
USART2_Init();
uint16_t light_level;
uint8_t human_detected;
uint16_t led_brightness = 0;
while (1) {
light_level = BH1750_ReadLight();
human_detected = Read_HC_SR501();
// 自动控制逻辑:如果光照低且有人,开启LED;否则关闭或调低
if (light_level < 100 && human_detected) { // 假设阈值100 lux
led_brightness = 1000; // 最大亮度假设为1000
} else {
led_brightness = 0;
}
Set_LED_Brightness(led_brightness);
// 准备数据上传华为云(通过ESP8266)
char buffer[64];
sprintf(buffer, "Light: %d lux, Human: %d, LED: %d\r\n", light_level, human_detected, led_brightness);
USART2_SendString(buffer); // 通过UART发送到ESP8266
Delay_ms(1000); // 每秒更新一次
}
}
void SystemInit(void) {
// 启用GPIOA、GPIOB、I2C1、TIM2、USART2时钟
RCC_APB2ENR |= (1 << 2) | (1 << 3) | (1 << 0); // GPIOA, GPIOB, AFIO
RCC_APB1ENR |= (1 << 0) | (1 << 22) | (1 << 17); // TIM2, I2C1, USART2
}
void GPIO_Init(void) {
// 配置PA0为输入(HC-SR501)
GPIOA_CRL &= ~(0xF << (HC_SR501_PIN * 4)); // 清除模式
GPIOA_CRL |= (0x4 << (HC_SR501_PIN * 4)); // 输入模式
// 配置PA1为输出(LED PWM,复用推挽输出)
GPIOA_CRL &= ~(0xF << (LED_PWM_PIN * 4));
GPIOA_CRL |= (0xB << (LED_PWM_PIN * 4)); // 复用推挽输出,50MHz
// 配置PA2和PA3为USART2复用推挽输出
GPIOA_CRL &= ~(0xFF << (ESP8266_TX_PIN * 4));
GPIOA_CRL |= (0xB << (ESP8266_TX_PIN * 4)); // TX:复用推挽输出
GPIOA_CRL |= (0x4 << (ESP8266_RX_PIN * 4)); // RX:输入浮空
// 配置PB6和PB7为I2C1复用开漏输出
GPIOB_CRL &= ~(0xFF << (I2C1_SCL_PIN * 4));
GPIOB_CRL |= (0xE << (I2C1_SCL_PIN * 4)); // SCL:复用开漏输出
GPIOB_CRL |= (0xE << (I2C1_SDA_PIN * 4)); // SDA:复用开漏输出
}
void I2C1_Init(void) {
I2C1_CR1 &= ~(1 << 0); // 禁用I2C1
I2C1_CR2 = 36; // 设置APB1时钟为36MHz,因此CR2=36
I2C1_CCR = 180; // 设置CCR for 100kHz: CCR = APB1 clock / (2 * I2C speed) = 36e6 / (2 * 100e3) = 180
I2C1_TRISE = 37; // 设置TRISE: TRISE = (APB1 clock / 1e6) + 1 = 36 + 1 = 37
I2C1_CR1 |= (1 << 0); // 启用I2C1
}
void I2C1_Start(void) {
I2C1_CR1 |= (1 << 8); // 生成START条件
while (!(I2C1_SR1 & (1 << 0))); // 等待SB标志置位
}
void I2C1_Stop(void) {
I2C1_CR1 |= (1 << 9); // 生成STOP条件
while (I2C1_SR2 & (1 << 1)); // 等待BUSY标志清除
}
void I2C1_Write(uint8_t data) {
I2C1_DR = data;
while (!(I2C1_SR1 & (1 << 7))); // 等待TxE标志置位
}
uint8_t I2C1_Read(uint8_t ack) {
if (ack) {
I2C1_CR1 |= (1 << 10); // 启用ACK
} else {
I2C1_CR1 &= ~(1 << 10); // 禁用ACK
}
while (!(I2C1_SR1 & (1 << 6))); // 等待RxNE标志置位
return I2C1_DR;
}
void BH1750_Init(void) {
I2C1_Start();
I2C1_Write(BH1750_ADDRESS << 1); // 写地址
I2C1_Write(BH1750_POWER_ON);
I2C1_Stop();
Delay_ms(10);
I2C1_Start();
I2C1_Write(BH1750_ADDRESS << 1);
I2C1_Write(BH1750_CONTINUOUS_HIGH_RES_MODE);
I2C1_Stop();
Delay_ms(180); // 等待测量完成
}
uint16_t BH1750_ReadLight(void) {
uint8_t msb, lsb;
uint16_t lux;
I2C1_Start();
I2C1_Write((BH1750_ADDRESS << 1) | 0x01); // 读地址
msb = I2C1_Read(1); // 读MSB,发送ACK
lsb = I2C1_Read(0); // 读LSB,不发送ACK
I2C1_Stop();
lux = (msb << 8) | lsb;
lux = lux / 1.2; // 转换为lux
return lux;
}
uint8_t Read_HC_SR501(void) {
return (GPIOA_IDR & (1 << HC_SR501_PIN)) ? 1 : 0; // 读取PA0状态
}
void TIM2_Init(void) {
TIM2_CR1 &= ~(1 << 0); // 禁用TIM2
TIM2_PSC = 71; // 预分频器:72MHz / (71+1) = 1MHz
TIM2_ARR = 999; // 自动重载值,PWM频率 = 1MHz / 1000 = 1kHz
TIM2_CCMR1 |= (0x6 << 4); // OC1M模式:PWM模式1
TIM2_CCER |= (1 << 0); // 启用CC1输出
TIM2_CR1 |= (1 << 0); // 启用TIM2
}
void Set_LED_Brightness(uint16_t brightness) {
if (brightness > 999) brightness = 999;
TIM2_CCR1 = brightness; // 设置CCR1值控制占空比
}
void USART2_Init(void) {
USART2_CR1 &= ~(1 << 13); // 禁用USART2
USART2_BRR = 0x1D4C; // 设置波特率115200:36e6 / 115200 = 312.5 -> 0x1D4C
USART2_CR1 |= (1 << 2) | (1 << 3); // 启用发送和接收
USART2_CR1 |= (1 << 13); // 启用USART2
}
void USART2_SendChar(char ch) {
while (!(USART2_SR & (1 << 7))); // 等待TxE标志
USART2_DR = ch;
}
void USART2_SendString(const char *str) {
while (*str) {
USART2_SendChar(*str++);
}
}
char USART2_ReceiveChar(void) {
while (!(USART2_SR & (1 << 5))); // 等待RxNE标志
return USART2_DR;
}
void Delay_ms(uint32_t ms) {
for (uint32_t i = 0; i < ms * 1000; i++) {
__asm__("nop"); // 简单延时,实际应用中使用定时器更准确
}
}
项目核心代码
#include "stm32f10x.h"
#include <stdio.h> // For sprintf
// Define pins and peripherals
#define PIR_GPIO_PORT GPIOA
#define PIR_GPIO_PIN GPIO_Pin_0
#define LED_GPIO_PORT GPIOA
#define LED_GPIO_PIN GPIO_Pin_1 // TIM2_CH2
#define I2C_PORT I2C1
#define I2C_SCL_PIN GPIO_Pin_6
#define I2C_SDA_PIN GPIO_Pin_7
#define I2C_GPIO_PORT GPIOB
#define USART_PORT USART2
#define USART_GPIO_PORT GPIOA
#define USART_TX_PIN GPIO_Pin_2
#define USART_RX_PIN GPIO_Pin_3
// Function prototypes
void RCC_Configuration(void);
void GPIO_Configuration(void);
void I2C1_Configuration(void);
void TIM2_Configuration(void);
void USART2_Configuration(void);
void Delay_ms(uint32_t ms);
extern uint16_t Read_Light(void); // Assume defined in other module
uint8_t Read_PIR(void);
void Set_LED_Brightness(uint8_t brightness);
void USART2_SendString(char *str);
void Process_Cloud_Command(void);
// Global variables
volatile uint16_t light_value = 0;
volatile uint8_t pir_state = 0;
volatile uint8_t led_brightness = 0;
char cloud_data[50];
int main(void) {
// Initialize system
RCC_Configuration();
GPIO_Configuration();
I2C1_Configuration();
TIM2_Configuration();
USART2_Configuration();
while(1) {
light_value = Read_Light();
pir_state = Read_PIR();
if (light_value < 50 && pir_state) {
Set_LED_Brightness(100);
} else if (light_value < 50 && !pir_state) {
Set_LED_Brightness(30);
} else {
Set_LED_Brightness(0);
}
sprintf(cloud_data, "Light:%d,PIR:%d,LED:%d", light_value, pir_state, led_brightness);
USART2_SendString(cloud_data);
Process_Cloud_Command();
Delay_ms(1000);
}
}
void RCC_Configuration(void) {
RCC->CR |= RCC_CR_HSEON;
while(!(RCC->CR & RCC_CR_HSERDY));
RCC->CFGR |= RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9;
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));
FLASH->ACR |= FLASH_ACR_LATENCY_2;
RCC->CFGR |= RCC_CFGR_SW_PLL;
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN;
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN | RCC_APB1ENR_TIM2EN | RCC_APB1ENR_USART2EN;
}
void GPIO_Configuration(void) {
GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0);
GPIOA->CRL |= GPIO_CRL_CNF0_0;
GPIOA->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1);
GPIOA->CRL |= GPIO_CRL_MODE1_1 | GPIO_CRL_CNF1_1;
GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6 | GPIO_CRL_MODE7 | GPIO_CRL_CNF7);
GPIOB->CRL |= GPIO_CRL_MODE6_1 | GPIO_CRL_CNF6_1 | GPIO_CRL_MODE7_1 | GPIO_CRL_CNF7_1;
GPIOA->CRL &= ~(GPIO_CRL_MODE2 | GPIO_CRL_CNF2 | GPIO_CRL_MODE3 | GPIO_CRL_CNF3);
GPIOA->CRL |= GPIO_CRL_MODE2_1 | GPIO_CRL_CNF2_1;
GPIOA->CRL |= GPIO_CRL_CNF3_0;
}
void I2C1_Configuration(void) {
I2C1->CR1 &= ~I2C_CR1_PE;
I2C1->CR2 = 36;
I2C1->CCR = 180;
I2C1->TRISE = 37;
I2C1->CR1 |= I2C_CR1_PE;
}
void TIM2_Configuration(void) {
TIM2->PSC = 719;
TIM2->ARR = 99;
TIM2->CCMR1 |= TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2;
TIM2->CCER |= TIM_CCER_CC2E;
TIM2->CR1 |= TIM_CR1_CEN;
}
void USART2_Configuration(void) {
USART2->BRR = 36000000 / 9600;
USART2->CR1 |= USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}
uint8_t Read_PIR(void) {
return (GPIOA->IDR & PIR_GPIO_PIN) ? 1 : 0;
}
void Set_LED_Brightness(uint8_t brightness) {
if (brightness > 100) brightness = 100;
TIM2->CCR2 = brightness;
led_brightness = brightness;
}
void USART2_SendString(char *str) {
while(*str) {
while(!(USART2->SR & USART_SR_TXE));
USART2->DR = *str++;
}
}
void Process_Cloud_Command(void) {
if (USART2->SR & USART_SR_RXNE) {
char data = USART2->DR;
if (data == '1') {
Set_LED_Brightness(100);
} else if (data == '0') {
Set_LED_Brightness(0);
}
}
}
void Delay_ms(uint32_t ms) {
for(uint32_t i = 0; i < ms * 1000; i++);
}
总结
本项目成功设计并实现了一个基于STM32F103C8T6微控制器与华为云物联网平台的智能楼宇照明控制系统。系统通过集成多种传感器和执行器,实现了对楼宇各区域照明环境的实时监测与自动控制,有效提升了照明管理的智能化水平和能源利用效率。
在硬件方面,系统以STM32F103C8T6最小系统核心板为主控制器,结合GY-30光照强度传感器和HC-SR501人体红外传感器,准确采集环境光照与人员活动数据。LED照明灯组通过LM2596降压模块支持PWM调光,实现对亮度的精细控制。ESP8266-01S Wi-Fi模块确保了与华为云平台的稳定通信,而洞洞板焊接和杜邦线连接方式体现了系统的模块化与可扩展性。
系统功能上,不仅实现了根据环境条件自动调节照明,还通过华为云平台实现了数据上传与远程监控。QT上位机提供了友好的人机界面,支持用户远程手动控制和历史数据曲线显示,增强了系统的实用性和可操作性。这为楼宇照明管理提供了数据驱动的决策支持,同时促进了节能降耗。
总体而言,该系统设计合理,运行稳定,具有良好的应用前景。它展示了物联网技术在智能楼宇领域的有效集成,为未来智能家居和建筑自动化系统的开发提供了参考和基础。
- 点赞
- 收藏
- 关注作者
评论(0)