??零知IDE 是一個真正屬于國人自己的開源軟件平臺,在開發效率上超越了Arduino平臺并且更加容易上手,大大降低了開發難度。零知開源在軟件方面提供了完整的學習教程和豐富示例代碼,讓不懂程序的工程師也能非常輕而易舉的搭建電路來創作產品,測試產品。快來動手試試吧!
?訪問零知實驗室,獲取更多實戰項目和教程資源吧!
www.lingzhilab.com
目錄
一、硬件連接部分
1.1 硬件清單
1.2 接線方案
1.3 具體接線圖
1.4 接線實物圖
二、關鍵代碼解析
2.1 主循環設計
2.2?紅外信號處理
2.3?顯示更新優化
2.4 風扇驅動控制
2.5 系統完整代碼
三、項目結果演示
3.1 操作流程
3.2 界面展示
3.3 視頻演示
四、JQC-3FF-S-Z工作原理
4.1 基本結構
4.2 動作機制
五、常見問題解答
Q1: 如何調整光控的靈敏度?
Q2: 如何修改定時時間?
Q3: 舵機轉動不流暢怎么辦?
(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)
項目資源整合
????????繼電器數據手冊:JQC-3FF-S-Z
????????顯示屏數據手冊:ST7789
????????通過本項目的學習,讀者可以掌握STM32開發的基本技能,了解繼電器控制原理,并學會如何設計用戶友好的交互界面。歡迎各位讀者在此基礎上進行擴展和改進,創造出更多有趣的智能家居應用!