零知开源基于STM32F103RBT6的智能风扇控制系统设计与实现
零知开源——基于STM32F103RBT6的智能风扇控制系统设计与实现
✔零知IDE 是一个真正属于国人自己的开源软件平台,在开发效率上超越了Arduino平台并且更加容易上手,大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码,让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品,测试产品。快来动手试试吧!
✔访问零知实验室,获取更多实战项目和教程资源吧!
(1)项目概述
本项目基于STM32F103RBT6主控芯片(零知标准板),设计并实现了一个功能丰富的智能风扇控制系统。融合了红外遥控、自动光控、定时关闭、睡眠模式等多种智能控制方式。系统采用JQC-3FF-S-Z继电器作为主要控制元件,通过红外遥控器实现远程控制,同时集成了光敏传感器实现环境光线自适应控制。
(2)项目难点及解决方案
问题描述:系统需要同时处理红外信号接收、舵机控制、传感器数据采集和显示更新等多个任务。
解决方案: 采用基于millis()的时间管理方法,避免使用delay(),确保系统响应及时
一、硬件连接部分
1.1 硬件清单
组件名称 | 型号/规格 | 数量 | 备注 |
---|---|---|---|
主控板 | 零知标准板(STM32F103RBT6) | 1 | 核心控制单元 |
继电器模块 | JQC-3FF-S-Z | 1 | 控制风扇电源 |
TFT显示屏 | ST7789 240x240 | 1 | 用户界面显示 |
红外控制模块 | IR Receiver红外接收模块 | 1 | 接收红外信号 |
舵机 | SG90 | 1 | 实现风扇摇头功能 |
光敏电阻 | 光敏电阻模块 | 1 | 环境光线检测 |
直流电机 | 3.3V | 1 | 被控对象 |
1.2 接线方案
注意:JQC-3FF-S-Z的D+接5V,其他器件电源接3.3V
组件 | 零知标准板引脚 | 说明 |
---|---|---|
继电器IN | 6 | 继电器控制引脚 |
红外接收DATA | 3 | 红外信号输入 |
舵机信号 | 5 | 舵机控制 |
TFT_SCL | 13 | 显示屏时钟线 |
TFT_SDA | 11 | 显示屏数据输入 |
TFT_CS | 10 | 显示屏片选 |
TFT_DC | 9 | 显示屏数据/命令 |
TFT_RST | 8 | 显示屏复位 |
光敏电阻OUT | 0 | 光线传感器信号 |
1.3 具体接线图
PS:直流电机的其中一极接3.3V电源,另一极接JQC-3FF-S-Z继电器的COM公共端
1.4 接线实物图
二、关键代码解析
2.1 主循环设计
void loop() {
// 处理红外信号
if (irrecv.decode(&results)) {
handleIRCommand(results.value);
irrecv.resume();
redrawNeeded = true;
}
// 处理舵机摆动
handleSwing();
// 处理定时器
handleTimer();
// 处理睡眠模式
handleSleepMode();
// 读取光线传感器数据
readLightSensor();
// 自动模式处理
if (operationMode == MODE_LIGHT_AUTO) {
handleAutoMode();
}
// 更新显示
updateDisplay();
delay(100); // 短暂延迟以减少CPU使用率
}
主循环采用非阻塞设计,通过状态标志控制各功能的执行,确保系统响应及时。
2.2 红外信号处理
void handleIRCommand(unsigned long value) {
Serial.print("IR Code Received: 0x");
Serial.println(value, HEX);
switch(value) {
case BTN_POWER:
togglePower();
break;
// 其他按键处理...
}
}
红外信号处理函数通过switch-case结构解析不同按键的功能,代码结构清晰易懂。
2.3 显示更新优化
void updateDisplay() {
// 只在需要时重绘
if (!redrawNeeded) {
// 对于定时器模式,每秒更新一次时间显示
if (operationMode == MODE_TIMER && timerActive) {
unsigned long currentTime = millis();
if (currentTime - lastTimerUpdate >= 1000) {
lastTimerUpdate = currentTime;
updateTimerDisplay();
}
}
// 省略其他模式...
return;
}
// 全屏刷新逻辑...
}
显示更新函数通过redrawNeeded标志控制刷新频率,避免不必要的屏幕刷新,提高系统效率。
2.4 风扇驱动控制
void turnOffFan() {
digitalWrite(RELAY_PIN, HIGH);
fanState = FAN_OFF;
swingState = SWING_OFF; // 关闭风扇时也停止摆动
timerActive = false; // 取消定时
sleepActive = false; // 取消睡眠模式
Serial.println("Fan Turned OFF");
}
void turnOnFan() {
digitalWrite(RELAY_PIN, LOW);
fanState = FAN_ON;
Serial.println("Fan Turned ON");
}
void handleSwing() {
if (swingState == SWING_OFF) return;
unsigned long currentTime = millis();
if (currentTime - lastSwingTime >= swingSpeed) {
lastSwingTime = currentTime;
// 摆动范围 20-160 度
static int direction = 1; // 1为增加角度,-1为减少角度
swingAngle += direction;
myservo.write(swingAngle);
// 到达边界时改变方向
if (swingAngle >= 160 || swingAngle <= 20) {
direction = -direction;
}
}
}
JQC-3FF-S-Z继电器模块控制风扇电源并设置标志位
2.5 系统完整代码
#include "IRremote.h"
#include "Servo.h"
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
// 引脚定义
#define IR_RECV_PIN 3 // 红外接收 DAT 引脚
#define RELAY_PIN 6 // 继电器控制引脚
#define SERVO_PIN 5 // 舵机控制引脚
#define TFT_CS 10 // TFT显示屏片选引脚
#define TFT_DC 9 // TFT显示屏数据/命令引脚
#define TFT_RST 8 // TFT显示屏复位引脚
#define LIGHT_SENSOR A0 // 光敏电阻引脚
// 红外按键编码
enum IR_CODES {
BTN_POWER = 0xFF30CF, // 按键1 - 电源开关
BTN_SWING = 0xFF18E7, // 按键2 - 摇头开关
BTN_TIMER_10 = 0xFF7A85, // 按键3 - 10秒定时
BTN_TIMER_30 = 0xFF10EF, // 按键4 - 30秒定时
BTN_MODE = 0xFF38C7, // 按键5 - 模式切换
BTN_SLEEP = 0xFF4AB5 // 按键8 - 睡眠模式
};
// 系统状态
enum FAN_STATE {
FAN_OFF,
FAN_ON
};
enum SWING_STATE {
SWING_OFF,
SWING_ON
};
enum OPERATION_MODE {
MODE_NORMAL,
MODE_LIGHT_AUTO,
MODE_TIMER,
MODE_SLEEP
};
// 全局变量
IRreceiver irrecv(IR_RECV_PIN);
IRdecode_results results;
Servo myservo;
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
int fanState = FAN_OFF;
int swingState = SWING_OFF;
int operationMode = MODE_NORMAL;
int swingAngle = 90; // 舵机角度
int swingSpeed = 15; // 舵机速度 (ms延迟,值越小越快)
unsigned long lastSwingTime = 0;
unsigned long timerStartTime = 0;
unsigned long timerDuration = 0;
bool timerActive = false;
unsigned long sleepStartTime = 0;
unsigned long sleepDuration = 5 * 1000; // 8小时睡眠模式 8 * 60 * 60 * 1000
bool sleepActive = false;
int lightLevel = 0;
int lastLightLevel = 0;
unsigned long lastTimerUpdate = 0;
bool redrawNeeded = true;
// 显示区域定义
#define STATUS_AREA 40
#define DATA_AREA 80
#define LIGHT_THRESHOLD 500 // 光线阈值
void setup() {
Serial.begin(9600);
// 初始化引脚
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, HIGH); // 初始关闭继电器
// 初始化红外接收和舵机
irrecv.enableIRIn();
myservo.attach(SERVO_PIN);
myservo.write(swingAngle); // 初始位置
// 初始化显示屏
tft.init(240, 240);
tft.setRotation(1);
tft.fillScreen(ST77XX_BLACK);
// 初始化光敏电阻
pinMode(LIGHT_SENSOR, INPUT);
// 显示准备界面
showReadyScreen();
Serial.println("\nSmart Fan Control System Started");
}
void loop() {
// 处理红外信号
if (irrecv.decode(&results)) {
handleIRCommand(results.value);
irrecv.resume();
redrawNeeded = true;
}
// 处理舵机摆动
handleSwing();
// 处理定时器
handleTimer();
// 处理睡眠模式
handleSleepMode();
// 读取光线传感器数据
readLightSensor();
// 自动模式处理
if (operationMode == MODE_LIGHT_AUTO) {
handleAutoMode();
}
// 更新显示
updateDisplay();
delay(100); // 短暂延迟以减少CPU使用率
}
void showReadyScreen() {
tft.fillScreen(ST77XX_BLACK);
// 显示标题
tft.setCursor(60, 80);
tft.setTextColor(ST77XX_CYAN);
tft.setTextSize(3);
tft.println("READY");
// 绘制进度条
tft.drawRect(20, 120, 200, 20, ST77XX_WHITE);
for (int i = 0; i <= 100; i += 5) {
tft.fillRect(20, 120, i * 2, 20, ST77XX_BLUE);
delay(50);
}
delay(1000);
tft.fillScreen(ST77XX_BLACK);
redrawNeeded = true;
}
void handleIRCommand(unsigned long value) {
Serial.print("IR Code Received: 0x");
Serial.println(value, HEX);
switch(value) {
case BTN_POWER:
togglePower();
break;
case BTN_SWING:
toggleSwing();
break;
case BTN_TIMER_10:
setTimer(10);
break;
case BTN_TIMER_30:
setTimer(30);
break;
case BTN_MODE:
switchMode();
break;
case BTN_SLEEP:
toggleSleepMode();
break;
default:
Serial.println("Unknown Command");
break;
}
}
void togglePower() {
if (fanState == FAN_OFF) {
turnOnFan();
} else {
turnOffFan();
}
}
void turnOffFan() {
digitalWrite(RELAY_PIN, HIGH);
fanState = FAN_OFF;
swingState = SWING_OFF; // 关闭风扇时也停止摆动
timerActive = false; // 取消定时
sleepActive = false; // 取消睡眠模式
Serial.println("Fan Turned OFF");
}
void turnOnFan() {
digitalWrite(RELAY_PIN, LOW);
fanState = FAN_ON;
Serial.println("Fan Turned ON");
}
void toggleSwing() {
if (fanState == FAN_OFF) {
Serial.println("Please Turn ON Fan First");
return;
}
swingState = !swingState;
Serial.print("Swing Function ");
Serial.println(swingState ? "Enabled" : "Disabled");
}
void setTimer(int seconds) {
if (fanState == FAN_OFF) {
Serial.println("Please Turn ON Fan First");
return;
}
timerDuration = seconds * 1000; // 转换为毫秒
timerStartTime = millis();
timerActive = true;
operationMode = MODE_TIMER;
redrawNeeded = true;
Serial.print("Timer Set: ");
Serial.print(seconds);
Serial.println(" seconds");
}
void switchMode() {
if (operationMode == MODE_NORMAL) {
operationMode = MODE_LIGHT_AUTO;
} else if (operationMode == MODE_LIGHT_AUTO) {
operationMode = MODE_NORMAL;
} else {
// 如果是定时器或睡眠模式,切换到普通模式
operationMode = MODE_NORMAL;
}
redrawNeeded = true;
if (operationMode == MODE_NORMAL) {
Serial.println("Normal Mode");
} else if (operationMode == MODE_LIGHT_AUTO) {
Serial.println("Light Auto Mode");
}
}
void toggleSleepMode() {
if (fanState == FAN_OFF) {
Serial.println("Please Turn ON Fan First");
return;
}
sleepActive = !sleepActive;
if (sleepActive) {
sleepStartTime = millis();
operationMode = MODE_SLEEP;
Serial.println("Sleep Mode Activated - Fan will turn off at 6 AM");
} else {
operationMode = MODE_NORMAL;
Serial.println("Sleep Mode Deactivated");
}
redrawNeeded = true;
}
void handleSwing() {
if (swingState == SWING_OFF) return;
unsigned long currentTime = millis();
if (currentTime - lastSwingTime >= swingSpeed) {
lastSwingTime = currentTime;
// 摆动范围 20-160 度
static int direction = 1; // 1为增加角度,-1为减少角度
swingAngle += direction;
myservo.write(swingAngle);
// 到达边界时改变方向
if (swingAngle >= 160 || swingAngle <= 20) {
direction = -direction;
}
}
}
void handleTimer() {
if (!timerActive) return;
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - timerStartTime;
if (elapsedTime >= timerDuration) {
turnOffFan();
operationMode = MODE_NORMAL;
Serial.println("Timer Finished - Fan Turned OFF");
redrawNeeded = true;
}
}
void handleSleepMode() {
if (!sleepActive) return;
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - sleepStartTime;
// 模拟6点关闭(8小时睡眠时间)
if (elapsedTime >= sleepDuration) {
turnOffFan();
sleepActive = false;
operationMode = MODE_NORMAL;
Serial.println("Sleep Mode Finished - Fan Turned OFF");
redrawNeeded = true;
}
}
void readLightSensor() {
// 读取光线强度
int newLightLevel = analogRead(LIGHT_SENSOR);
// 添加一些滤波以减少噪声
lightLevel = (lightLevel * 0.7) + (newLightLevel * 0.3);
}
void handleAutoMode() {
if (operationMode != MODE_LIGHT_AUTO) return;
if (fanState == FAN_OFF && lightLevel < LIGHT_THRESHOLD) {
turnOnFan();
Serial.println("Low Light - Auto ON");
redrawNeeded = true;
}
if (fanState == FAN_ON && lightLevel >= LIGHT_THRESHOLD) {
turnOffFan();
Serial.println("Bright Light - Auto OFF");
redrawNeeded = true;
}
}
void updateDisplay() {
// 只在需要时重绘
if (!redrawNeeded) {
// 对于定时器模式,每秒更新一次时间显示
if (operationMode == MODE_TIMER && timerActive) {
unsigned long currentTime = millis();
if (currentTime - lastTimerUpdate >= 1000) {
lastTimerUpdate = currentTime;
updateTimerDisplay();
}
}
// 对于睡眠模式,每分钟更新一次时间显示
else if (operationMode == MODE_SLEEP && sleepActive) {
unsigned long currentTime = millis();
if (currentTime - lastTimerUpdate >= 10000) {
lastTimerUpdate = currentTime;
updateSleepDisplay();
}
}
return;
}
lastLightLevel = lightLevel;
// 清除整个屏幕
tft.fillScreen(ST77XX_BLACK);
// 绘制标题和模式指示器
tft.setCursor(20, 10);
tft.setTextColor(ST77XX_CYAN);
tft.setTextSize(2);
tft.println("SMART FAN");
// 绘制模式指示器
uint16_t modeColor;
String modeText;
switch(operationMode) {
case MODE_NORMAL:
modeColor = ST77XX_BLUE;
modeText = "NORM";
break;
case MODE_LIGHT_AUTO:
modeColor = ST77XX_GREEN;
modeText = "AUTO";
break;
case MODE_TIMER:
modeColor = ST77XX_YELLOW;
modeText = "TIMER";
break;
case MODE_SLEEP:
modeColor = ST77XX_MAGENTA;
modeText = "SLEEP";
break;
}
tft.fillRect(180, 10, 50, 20, modeColor);
tft.setCursor(185, 15);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
tft.println(modeText);
// 绘制分隔线
tft.drawFastHLine(10, 35, 220, ST77XX_WHITE);
// 根据模式更新显示
switch(operationMode) {
case MODE_NORMAL:
updateNormalModeDisplay();
break;
case MODE_LIGHT_AUTO:
updateLightModeDisplay();
break;
case MODE_TIMER:
updateTimerDisplay();
break;
case MODE_SLEEP:
updateSleepDisplay();
break;
}
redrawNeeded = false;
lastTimerUpdate = millis();
}
void updateNormalModeDisplay() {
// 清除数据区域
tft.fillRect(10, STATUS_AREA, 220, 200, ST77XX_BLACK);
// 显示风扇状态
tft.setCursor(20, 50);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.print("FAN: ");
tft.setTextColor(fanState == FAN_ON ? ST77XX_GREEN : ST77XX_RED);
tft.println(fanState == FAN_ON ? "ON" : "OFF");
// 显示摇头状态
tft.setCursor(20, 80);
tft.setTextColor(ST77XX_WHITE);
tft.print("SWING: ");
tft.setTextColor(swingState == SWING_ON ? ST77XX_GREEN : ST77XX_RED);
tft.println(swingState == SWING_ON ? "ON" : "OFF");
// 显示舵机速度
tft.setCursor(20, 110);
tft.setTextColor(ST77XX_WHITE);
tft.print("SPEED: ");
tft.setTextColor(ST77XX_YELLOW);
tft.print(swingSpeed);
tft.println("ms");
// 显示光线数据
tft.setCursor(20, 140);
tft.setTextColor(ST77XX_WHITE);
tft.print("LIGHT: ");
tft.setTextColor(ST77XX_GREEN);
tft.println(lightLevel);
// 底部状态栏
tft.fillRect(0, 220, 240, 20, ST77XX_BLUE);
tft.setCursor(70, 225);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
tft.print("NORMAL MODE");
}
void updateLightModeDisplay() {
// 清除数据区域
tft.fillRect(10, STATUS_AREA, 220, 200, ST77XX_BLACK);
// 显示标题
tft.setCursor(20, 50);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.println("LIGHT CONTROL");
// 显示光线数据
tft.setCursor(20, 80);
tft.setTextColor(ST77XX_WHITE);
tft.print("LIGHT: ");
tft.setTextColor(ST77XX_GREEN);
tft.println(lightLevel);
// 显示阈值信息
tft.setCursor(20, 110);
tft.setTextColor(ST77XX_WHITE);
tft.print("THRESHOLD: ");
tft.setTextColor(ST77XX_YELLOW);
tft.println(LIGHT_THRESHOLD);
// 显示控制状态
tft.setCursor(20, 140);
tft.setTextColor(ST77XX_WHITE);
tft.print("CONTROL: ");
if (lightLevel < LIGHT_THRESHOLD) {
tft.setTextColor(ST77XX_GREEN);
tft.println("FAN ON");
} else {
tft.setTextColor(ST77XX_RED);
tft.println("FAN OFF");
}
// 显示当前风扇状态
tft.setCursor(20, 170);
tft.setTextColor(ST77XX_WHITE);
tft.print("FAN: ");
tft.setTextColor(fanState == FAN_ON ? ST77XX_GREEN : ST77XX_RED);
tft.println(fanState == FAN_ON ? "ON" : "OFF");
// 底部状态栏
tft.fillRect(0, 220, 240, 20, ST77XX_GREEN);
tft.setCursor(70, 225);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
tft.print("AUTO LIGHT MODE");
}
void updateTimerDisplay() {
// 清除数据区域
tft.fillRect(10, STATUS_AREA, 220, 200, ST77XX_BLACK);
// 显示标题
tft.setCursor(20, 50);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.println("TIMER MODE");
// 显示剩余时间
tft.setCursor(20, 80);
tft.setTextColor(ST77XX_WHITE);
tft.print("TIME LEFT: ");
if (timerActive) {
unsigned long remaining = (timerDuration - (millis() - timerStartTime)) / 1000;
tft.setTextColor(ST77XX_YELLOW);
tft.print(remaining);
tft.println("s");
} else {
tft.setTextColor(ST77XX_RED);
tft.println("INACTIVE");
}
// 显示风扇状态
tft.setCursor(20, 110);
tft.setTextColor(ST77XX_WHITE);
tft.print("FAN: ");
tft.setTextColor(fanState == FAN_ON ? ST77XX_GREEN : ST77XX_RED);
tft.println(fanState == FAN_ON ? "ON" : "OFF");
// 底部状态栏
tft.fillRect(0, 220, 240, 20, ST77XX_YELLOW);
tft.setCursor(90, 225);
tft.setTextColor(ST77XX_BLACK);
tft.setTextSize(1);
tft.print("TIMER MODE");
}
void updateSleepDisplay() {
// 清除数据区域
tft.fillRect(10, STATUS_AREA, 220, 200, ST77XX_BLACK);
// 显示标题
tft.setCursor(20, 50);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.println("SLEEP MODE");
// 显示剩余时间
tft.setCursor(20, 80);
tft.setTextColor(ST77XX_WHITE);
tft.print("TIME LEFT: ");
if (sleepActive) {
unsigned long remaining = (sleepDuration - (millis() - sleepStartTime)) / 1000;
unsigned long hours = remaining / 3600;
unsigned long minutes = (remaining % 3600) / 60;
tft.setTextColor(ST77XX_MAGENTA);
tft.print(hours);
tft.print("h ");
tft.print(minutes);
tft.println("m");
} else {
tft.setTextColor(ST77XX_RED);
tft.println("INACTIVE");
}
// 显示关闭时间
tft.setCursor(20, 110);
tft.setTextColor(ST77XX_WHITE);
tft.print("TURNS OFF: ");
tft.setTextColor(ST77XX_YELLOW);
tft.println("6:00 AM");
// 显示风扇状态
tft.setCursor(20, 140);
tft.setTextColor(ST77XX_WHITE);
tft.print("FAN: ");
tft.setTextColor(fanState == FAN_ON ? ST77XX_GREEN : ST77XX_RED);
tft.println(fanState == FAN_ON ? "ON" : "OFF");
// 底部状态栏
tft.fillRect(0, 220, 240, 20, ST77XX_MAGENTA);
tft.setCursor(90, 225);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
tft.print("SLEEP MODE");
}
模块名称 | 核心职责 | 关键函数 |
---|---|---|
红外遥控 | 接收并解析红外按键指令,映射到对应功能 | handleIRCommand() 、togglePower() |
风扇动作控制 | 控制风扇电源(继电器)和摇头(舵机) | turnOnFan() 、turnOffFan()等 |
模式控制 | 管理普通、光线自动、定时、睡眠 4 种工作模式 | switchMode() 、handleAutoMode() |
传感器数据 | 读取并滤波光敏传感器数据,为自动模式提供依据 | readLightSensor() |
显示驱动 | 控制 TFT 屏显示系统状态(定时 / 睡眠剩余时间) | updateTimerDisplay()等 |
三、项目结果演示
3.1 操作流程
(1)系统启动
上电后系统显示准备界面,完成自检后进入主界面
(2)系统控制
“电源键:开关风扇、“摇头键:启用/禁用摇头功能、“模式键:切换普通/光控模式 定时功能:设置10秒 / 30秒后系统自动关闭、启用睡眠模式 8 小时自动关闭
3.2 界面展示
(1)普通模式界面
显示风扇状态、摇头状态、舵机速度和光线值
(2)光控模式界面
显示光线值、阈值和控制状态
(3)定时模式界面
显示剩余时间和风扇状态
(4)睡眠模式界面
显示剩余时间和关闭时间
3.3 视频演示
JQC-3FF-S-Z继电器驱动小风扇
红外遥控操作控制智能风扇实现自动光控功能、摇头功能、模式切换以及系统定时功能
四、JQC-3FF-S-Z工作原理
4.1 基本结构
继电器主要由电磁线圈、铁芯、铁片(衔铁)、复位弹簧、常开触点和常闭触点等部分组成。
4.2 动作机制
根据触点的动作形式,可分为常闭式和常开式。常闭式继电器在未通电时触点闭合,通电后断开;常开式继电器在未通电时触点断开,通电后闭合。
电器的动作机制基于电磁感应原理。当线圈通电后,产生的磁场使铁心运动,带动与铁心相连的触点动作。
五、常见问题解答
Q1: 如何调整光控的灵敏度?
A: 修改代码中的LIGHT_THRESHOLD值:
值越小,对光线越敏感(更容易触发)。值越大,需要更暗的环境才会触发
Q2: 如何修改定时时间?
A: 在setTimer函数中修改时间参数,或者添加更多的定时选项:
void setTimer(int seconds) {
// 修改这里的seconds参数即可
timerDuration = seconds * 1000;
// ...
}
Q3: 舵机转动不流畅怎么办?
A: 调整swingSpeed参数:
值越小,转动越快。值越大,转动越慢(建议范围5-30ms)
项目资源整合
继电器数据手册:
显示屏数据手册:
通过本项目的学习,读者可以掌握STM32开发的基本技能,了解继电器控制原理,并学会如何设计用户友好的交互界面。欢迎各位读者在此基础上进行扩展和改进,创造出更多有趣的智能家居应用!