基于stm32的智能家居

99ANYc3cd6
预计阅读时长 34 分钟
位置: 首页 AI智能 正文

项目概述

目标: 设计并实现一个基于STM32的智能家居控制系统,能够通过按键、手机APP或网页远程控制家中的LED灯、风扇等设备,并实时监测环境温湿度。

基于stm32的智能家居
(图片来源网络,侵删)

核心特点:

  1. 本地控制: 通过物理按键直接控制设备。
  2. 无线远程控制: 通过Wi-Fi或蓝牙连接手机,实现远程控制。
  3. 状态反馈: 将设备状态(开关)和环境数据(温湿度)实时反馈到用户端。
  4. 可扩展性: 硬件和软件设计应易于扩展新的传感器和执行器。

核心模块与硬件选型

一个典型的智能家居系统由以下几个部分组成:

模块 功能 推荐硬件(基于STM32) 备注
主控单元 大脑,处理所有逻辑和数据 STM32F103C8T6 (Blue Pill) 或 STM32F407VGT6 (Black Pill) F103性价比高,足够用;F407性能更强,适合运行复杂协议或带屏幕。
无线通信 连接手机/网络 ESP8266-01S (Wi-Fi模块) 或 HC-05/HC-06 (蓝牙模块) ESP8266功能强大,可做TCP服务器/客户端,适合物联网;蓝牙适合近距离控制。
传感器 感知环境 DHT11/DHT22 (温湿度传感器) DHT11便宜,DHT22精度更高。
执行器 控制物理设备 5V继电器模块 (控制灯、风扇等) 通过STM32的GPIO控制继电器吸合/断开来开关220V设备(注意安全!)。
人机交互 本地操作与显示 按键LED指示灯OLED显示屏 (0.96寸 I2C) 按键用于手动控制,LED显示设备状态,OLED可显示更多信息。
电源模块 提供稳定供电 USB转TTL (5V)独立5V/3.3V电源适配器 为整个系统供电,继电器部分可能需要独立供电。

硬件连接示意图

                  +-----------------+
                  |    STM32 MCU    |
                  | (e.g., F103C8T6)|
                  +--------+--------+
                           |
        +-------------------+-------------------+
        |                   |                   |
+-------v------+   +--------v--------+   +------v------+
|  ESP8266     |   |   DHT11/DHT22   |   |  继电器模块 |
| (Wi-Fi)      |   | (温湿度)        |   | (控制风扇)  |
+-------+------+   +--------+--------+   +------+------+
        |                   |                   |
        | (UART: TX/RX)     | (GPIO: Data)     | (GPIO: IN)
        +-------------------+-------------------+
                           |
                  +--------v--------+
                  |   按键 & LED    |
                  | (本地控制)      |
                  +-----------------+

软件架构与开发流程

我们采用分层架构,使代码结构清晰,易于维护和移植。

  1. 硬件抽象层: 直接操作STM32的寄存器或使用标准库/库函数,实现对GPIO、UART、I2C等外设的控制。
  2. 驱动层: 封装底层硬件,提供简单的API。LED_On(), Relay_Toggle(), DHT11_Read()
  3. 协议层: 实现设备间的通信协议,与ESP8266通过AT指令集通信,或自定义简单的应用层协议。
  4. 应用层: 实现核心业务逻辑,如按键处理、数据解析、状态机、定时任务等。
  5. 用户接口层: 处理来自本地(按键)和远程(Wi-Fi/蓝牙)的命令,并生成反馈数据。

开发流程

  1. 环境搭建:

    基于stm32的智能家居
    (图片来源网络,侵删)
    • 安装 Keil MDKSTM32CubeIDE
    • 安装 STM32CubeMX(图形化配置工具,强烈推荐)。
    • 安装 串口调试助手 (如 SSCOM, MobaXterm)。
  2. 基础外设配置 (使用STM32CubeMX):

    • SYS: 设置 DebugSerial Wire
    • RCC: 配置外部晶振(如果使用)。
    • GPIO: 配置按键输入(上拉/下拉)、LED和继电器控制引脚为输出。
    • UART: 配置与ESP8266通信的串口(如USART1),设置波特率(通常是115200)。
    • I2C: 配置与OLED和DHT11(如果使用I2C版本)通信的I2C接口(如I2C1)。
    • 生成代码: 生成MDK或IDE工程。

核心代码示例

驱动层示例:DHT11温湿度读取

DHT11是单总线协议,需要精确的时序控制,这里提供一个基于HAL库的示例函数。

// dht11.h
#ifndef __DHT11_H
#define __DHT11_H
#include "main.h"
#include "stdint.h"
typedef struct {
    float temperature;
    float humidity;
    uint8_t error;
} DHT11_Data;
void DHT11_Init(void);
DHT11_Data DHT11_ReadData(void);
#endif
// dht11.c
#include "dht11.h"
#define DHT11_PORT  GPIOA
#define DHT11_PIN   GPIO_PIN_8
void DHT11_Start(void) {
    HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET); // 拉低
    HAL_Delay(20); // 拉低至少18ms
    HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET); // 拉高
    HAL_Delay(30); // 等待DHT11响应
}
uint8_t DHT11_ReadByte(void) {
    uint8_t i, data = 0;
    for (i = 0; i < 8; i++) {
        while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_RESET); // 等待50us高电平结束
        HAL_Delay(40); // 判断高电平持续时间
        if (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET) {
            data |= (1 << (7 - i)); // 高电平持续时间较长,为1
            while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET); // 等待这一位结束
        } else {
            data &= ~(1 << (7 - i)); // 高电平持续时间较短,为0
        }
    }
    return data;
}
DHT11_Data DHT11_ReadData(void) {
    DHT11_Data data = {0};
    uint8_t buf[5];
    DHT11_Start();
    // 等待DHT11响应
    if (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET) {
        data.error = 1;
        return data;
    }
    while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET);
    while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_RESET);
    while (HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) == GPIO_PIN_SET);
    // 读取40位数据
    for (int i = 0; i < 5; i++) {
        buf[i] = DHT11_ReadByte();
    }
    // 校验和检查
    if (buf[0] + buf[1] + buf[2] + buf[3] == buf[4]) {
        data.humidity = buf[0] + buf[1] / 10.0;
        data.temperature = buf[2] + buf[3] / 10.0;
    } else {
        data.error = 2; // 校验和错误
    }
    return data;
}

协议层示例:通过ESP8266发送数据 (AT指令)

ESP8266工作在Station模式,连接到路由器后,作为TCP客户端向服务器发送数据。

#include "stdio.h"
#include "string.h"
#include "usart.h" // 假设已封装好串口发送函数
// AT指令发送函数
void ESP8266_SendAT(const char* cmd, uint32_t timeout) {
    HAL_UART_Transmit(&huart1, (uint8_t*)cmd, strlen(cmd), timeout);
    HAL_UART_Transmit(&huart1, (uint8_t*)"\r\n", 2, timeout);
}
// ESP8266初始化并连接WiFi
void ESP8266_InitAndConnect(const char* ssid, const char* password, const char* server_ip, uint16_t server_port) {
    char cmd_buffer[100];
    // 1. 测试AT指令
    ESP8266_SendAT("AT", 100);
    // 等待返回 "OK"
    // 2. 设置为Station模式
    ESP8266_SendAT("AT+CWMODE=1", 100);
    // 3. 连接WiFi
    sprintf(cmd_buffer, "AT+CWJAP=\"%s\",\"%s\"", ssid, password);
    ESP8266_SendAT(cmd_buffer, 10000); // 连接可能需要较长时间
    // 4. 创建TCP连接
    sprintf(cmd_buffer, "AT+CIPSTART=\"TCP\",\"%s\",%d", server_ip, server_port);
    ESP8266_SendAT(cmd_buffer, 2000);
}
// 发送传感器数据到服务器
void SendDataToServer(float temp, float humi) {
    char data_str[50];
    sprintf(data_str, "Temp: %.1fC, Humi: %.1f%%", temp, humi);
    char cmd_buffer[20];
    int len = strlen(data_str);
    sprintf(cmd_buffer, "AT+CIPSEND=%d", len);
    // 发送发送数据长度的AT指令
    ESP8266_SendAT(cmd_buffer, 100);
    // 等待返回 "OK"
    // 发送实际数据
    HAL_UART_Transmit(&huart1, (uint8_t*)data_str, len, 100);
    // 等待发送完成
}

应用层示例:主循环逻辑

main.cwhile(1) 循环中整合所有功能。

// main.c
// 假设这些引脚已定义
#define LED_PIN GPIO_PIN_5
#define LED_PORT GPIOA
#define RELAY_PIN GPIO_PIN_6
#define RELAY_PORT GPIOA
#define KEY_PIN GPIO_PIN_7
#define KEY_PORT GPIOA
// 全局变量
DeviceState g_DeviceState = {0}; // 定义一个结构体来存储设备状态
int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init(); // 与ESP8266通信
    MX_I2C1_Init();       // 与OLED通信
    // 初始化外设
    OLED_Init();
    ESP8266_InitAndConnect("YourWiFiSSID", "YourPassword", "192.168.1.100", 8080);
    // 设置按键中断(可选,推荐用轮询)
    // ...
    while (1) {
        // 1. 本地按键检测
        if (HAL_GPIO_ReadPin(KEY_PORT, KEY_PIN) == GPIO_PIN_RESET) { // 假设按键按下为低电平
            HAL_Delay(50); // 消抖
            if (HAL_GPIO_ReadPin(KEY_PORT, KEY_PIN) == GPIO_PIN_RESET) {
                g_DeviceState.fan_state = !g_DeviceState.fan_state;
                HAL_GPIO_WritePin(RELAY_PORT, RELAY_PIN, g_DeviceState.fan_state ? GPIO_PIN_SET : GPIO_PIN_RESET);
                HAL_GPIO_WritePin(LED_PORT, LED_PIN, g_DeviceState.fan_state ? GPIO_PIN_SET : GPIO_PIN_RESET);
            }
            while (HAL_GPIO_ReadPin(KEY_PORT, KEY_PIN) == GPIO_PIN_RESET); // 等待按键释放
        }
        // 2. 读取传感器数据
        DHT11_Data dht_data = DHT11_ReadData();
        if (dht_data.error == 0) {
            g_DeviceState.temperature = dht_data.temperature;
            g_DeviceState.humidity = dht_data.humidity;
            // 在OLED上显示
            OLED_ShowString(0, 0, "Temp: ");
            OLED_ShowNum(50, 0, (int)dht_data.temperature, 2);
            OLED_ShowString(80, 0, "C");
            OLED_ShowString(0, 2, "Humi: ");
            OLED_ShowNum(50, 2, (int)dht_data.humidity, 2);
            OLED_ShowString(80, 2, "%");
        }
        // 3. 通过Wi-Fi发送数据 (例如每5秒一次)
        static uint32_t last_send_time = 0;
        if (HAL_GetTick() - last_send_time > 5000) {
            last_send_time = HAL_GetTick();
            SendDataToServer(g_DeviceState.temperature, g_DeviceState.humidity);
        }
        HAL_Delay(100); // 主循环延时
    }
}

远程控制方案

要实现手机APP或网页控制,你需要一个服务器作为中介。

方案A: ESP8266作为TCP服务器(简单)

  • 工作方式: ESP8266自己创建一个TCP服务器,手机APP作为客户端连接到它。
  • 优点: 不需要额外的服务器,成本低。
  • 缺点: ESP8266处理能力有限,能同时连接的客户端少;手机需要知道ESP8266的公网IP(如果不在内网)。
  • 实现:
    1. ESP8266发送 AT+CIPMUX=1 (允许多连接)。
    2. ESP8266发送 AT+CIPSERVER=1, 8080 (在端口8080上开启服务器)。
    3. STM32监听串口,当收到来自客户端的数据(如 FAN_ON),就解析并控制继电器。

方案B: 自建服务器(推荐)

  • 工作方式:
    1. ESP8266连接到你的家庭Wi-Fi。
    2. ESP8266作为TCP客户端,连接到你自建的服务器(可以用Python、Node.js等语言写)。
    3. 手机APP也连接到同一个服务器。
    4. STM32将数据发送给服务器,服务器再将数据广播给所有连接的手机APP,手机APP的指令也通过服务器传给STM32。
  • 优点: 稳定、可扩展、支持多用户、可以实现更复杂的逻辑(如定时、场景)。
  • 缺点: 需要一台一直开机的电脑或树莓派作为服务器,或使用云服务器。

方案C: 使用IoT云平台(最方便)

  • 工作方式: 将设备数据上传到阿里云IoT、腾讯云IoT、Blynk、ThingSpeak等平台,这些平台提供了强大的API、数据可视化和手机APP SDK。
  • 优点: 开发周期短,平台稳定,无需关心后端细节。
  • 缺点: 可能有费用,数据隐私需要考虑。

未来扩展方向

  1. 增加更多传感器: 烟雾传感器、人体红外传感器、光照传感器、门窗磁传感器等。
  2. 增加更多执行器: 伺服电机(控制窗帘)、舵机、蜂鸣器等。
  3. 增加本地显示: 使用TFT-LCD彩屏,制作更精美的UI。
  4. 实现语音控制: 集成语音识别模块(如LD3320)或连接到云语音API。
  5. 实现自动化场景: 当检测到光照不足且有人存在时,自动开灯。
  6. 加入安全机制: 对远程指令进行鉴权,防止非法控制。

这个项目从简单的LED控制开始,逐步加入传感器和无线通信,最终可以演变成一个功能完善的智能家居系统,祝你学习愉快,项目成功!

-- 展开阅读全文 --
头像
Inspiron 3420拆机清灰步骤有哪些?
« 上一篇 01-09
小蚁智能摄像机app下载在哪找?
下一篇 » 01-09

相关文章

取消
微信二维码
支付宝二维码

最近发表

标签列表

目录[+]