91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

零知IDE——基于零知標(biāo)準(zhǔn)板驅(qū)動(dòng)PAJ7620U2手勢(shì)控制L9110風(fēng)扇模塊和SG90舵機(jī)系統(tǒng)

零知實(shí)驗(yàn)室 ? 來(lái)源:PCB56242069 ? 作者:PCB56242069 ? 2026-01-06 11:10 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

? ?零知開源(零知IDE)是一個(gè)專為電子初學(xué)者/電子興趣愛好者設(shè)計(jì)的開源軟硬件平臺(tái),在硬件上提供超高性價(jià)比STM32系列開發(fā)板、物聯(lián)網(wǎng)控制板。取消了Bootloader程序燒錄,讓開發(fā)重心從“配置環(huán)境”轉(zhuǎn)移到“創(chuàng)意實(shí)現(xiàn)”,極大降低了技術(shù)門檻。零知IDE編程軟件,內(nèi)置上千個(gè)覆蓋多場(chǎng)景的示例代碼,支持項(xiàng)目源碼一鍵下載,項(xiàng)目文章在線瀏覽。零知開源(零知IDE)平臺(tái)通過軟硬件協(xié)同創(chuàng)新,讓你的創(chuàng)意快速轉(zhuǎn)化為實(shí)物,來(lái)動(dòng)手試試吧!

?訪問零知實(shí)驗(yàn)室,獲取更多實(shí)戰(zhàn)項(xiàng)目和教程資源吧!

www.lingzhilab.com

?

項(xiàng)目概述

本項(xiàng)目使用零知標(biāo)準(zhǔn)板(主控芯片:STM32F103RBT6)作為核心控制器,結(jié)合PAJ7620U2手勢(shì)傳感器實(shí)現(xiàn)對(duì)L9110風(fēng)扇模塊和SG90舵機(jī)的智能控制。系統(tǒng)通過識(shí)別9種不同的手勢(shì)動(dòng)作(上下、左右、順時(shí)針/逆時(shí)針、揮手、前推、后拉)分別控制風(fēng)扇的啟停、正反轉(zhuǎn)、調(diào)速以及舵機(jī)的精確角度定位,實(shí)現(xiàn)了無(wú)接觸式智能交互體驗(yàn)

項(xiàng)目難點(diǎn)及解決方案

問題描述:零知標(biāo)準(zhǔn)板的analogWrite()函數(shù)導(dǎo)致系統(tǒng)卡死

解決方案:放棄analogWrite()函數(shù),手動(dòng)配置STM32硬件定時(shí)器,直接操作定時(shí)器寄存器

一、系統(tǒng)接線部分

1.1 硬件清單

名稱 型號(hào)/參數(shù) 數(shù)量 說明
主控板 零知標(biāo)準(zhǔn)板 (STM32F103RBT6) 1 核心控制器
擴(kuò)展板 零知標(biāo)準(zhǔn)板-擴(kuò)展板 1 傳感器擴(kuò)展板
手勢(shì)傳感器 PAJ7620U2 1 I2C接口,識(shí)別9種手勢(shì)
風(fēng)扇驅(qū)動(dòng)模塊 L9110 / L9110S 1 雙路H橋,控制電機(jī)正反轉(zhuǎn)
舵機(jī) SG90 (180度) 1 控制風(fēng)向擺動(dòng)
杜邦線 公對(duì)母/公對(duì)公 若干 連接線

1.2 接線方案表

注意:請(qǐng)嚴(yán)格按照以下代碼定義的引腳進(jìn)行連接,否則程序無(wú)法正常工作。

模塊 引腳名稱 連接到零知標(biāo)準(zhǔn)板 (STM32) 功能說明
PAJ7620U2 VIN 3.3V 通常是3.3V邏輯電平
GND GND 地線
SCL SCL (或?qū)?yīng)I2C SCL) I2C 時(shí)鐘
SDA SDA (或?qū)?yīng)I2C SDA) I2C 數(shù)據(jù)線
SG90 舵機(jī) 信號(hào)線 (橙) 12 PWM控制信號(hào)
VCC (紅) 3.3V(直插拓展板) 電源
GND (棕) GND 電源地
L9110 風(fēng)扇 INA 9(PB7) 電機(jī)控制腳A
INB 5(PB6) 電機(jī)控制腳B
VCC 5V (建議外接) 電源正
GND GND 電源地

PS:本項(xiàng)目采用擴(kuò)展板直插零知標(biāo)準(zhǔn)板,請(qǐng)注意I2C接口線序,與開發(fā)板定義的內(nèi)容不一致,需要將外接的帶鎖扣端子轉(zhuǎn)杜邦線調(diào)整為VIN、GND、SCL和SDA;舵機(jī)直插D12 PWM接口,舵機(jī)黃色信號(hào)線靠近''D12''絲印一端

?

1.3 具體接線圖

wKgZO2lcbh2AWHKRAALuL-mSYRw421.png

請(qǐng)注意:如果風(fēng)扇使用外部電源,務(wù)必將外部電源的負(fù)極(-)連接到零知標(biāo)準(zhǔn)板的 GND,否則控制信號(hào)無(wú)法形成回路

?

1.4 接線實(shí)物圖

wKgZO2lcbkaAAWrqAAENNeh9n7E842.png

二、安裝與使用部分

2.1 開源平臺(tái)-輸入"PAJ7620U2"并搜索-代碼下載自動(dòng)打開

wKgZO2lcbnmAaebPAAJcmnhhNm0654.png

2.2 連接-驗(yàn)證-上傳

wKgZO2lcbqGAUGMeAAMkZwwYziU923.png

2.3 調(diào)試-串口監(jiān)視器

wKgZO2lcbqmAXIPIAAL0QvFNYac824.png

三、代碼講解部分

本項(xiàng)目的代碼結(jié)構(gòu)清晰,采用了模塊化設(shè)計(jì),代碼從初始化、手勢(shì)處理邏輯和硬件控制部分展開

3.1 軟件I2C配置

//1. I2C寫寄存器
uint8_t RevEng_PAJ7620::writeRegister(uint8_t i2cAddress, uint8_t dataByte) {
  wireHandle->beginTransmission(PAJ7620_I2C_BUS_ADDR);  // 0x73
  wireHandle->write(i2cAddress);   // 寄存器地址
  wireHandle->write(dataByte);     // 數(shù)據(jù)
  return wireHandle->endTransmission();
}

//2. I2C讀寄存器
uint8_t RevEng_PAJ7620::readRegister(uint8_t i2cAddress, uint8_t byteCount, uint8_t data[]) {
  wireHandle->beginTransmission(PAJ7620_I2C_BUS_ADDR);
  wireHandle->write(i2cAddress);
  uint8_t result = wireHandle->endTransmission();
  if (result) return result;  // 通信錯(cuò)誤
  
  wireHandle->requestFrom((int)PAJ7620_I2C_BUS_ADDR, (int)byteCount);
  while (wireHandle->available()) {
    *data = wireHandle->read();
    data++;
  }
  return 0;
}

軟件I2C通過GPIO模擬I2C時(shí)序,雖然速度略慢,但穩(wěn)定性更高

3.2平滑移動(dòng)算法

// 平滑移動(dòng)舵機(jī)(防止舵機(jī)快速轉(zhuǎn)動(dòng)時(shí)抖動(dòng)或損壞)
void moveServoSmoothly() {
  int step = 2;  // 默認(rèn)每次移動(dòng)2度

  // 根據(jù)目標(biāo)位置調(diào)整移動(dòng)步長(zhǎng)
  // 如果是移動(dòng)到0度或180度(左右手勢(shì)),使用較大步長(zhǎng)實(shí)現(xiàn)快速響應(yīng)
  if (targetServoPos == 0 || targetServoPos == 180) {
    step = 5;  // 大步長(zhǎng),快速移動(dòng)
  }

  // 根據(jù)當(dāng)前位置和目標(biāo)位置的關(guān)系,逐步移動(dòng)
  if (currentServoPos < targetServoPos) {
    // 當(dāng)前位置小于目標(biāo)位置,向右轉(zhuǎn)
    currentServoPos = min(currentServoPos + step, targetServoPos);
  } 
  else if (currentServoPos > targetServoPos) {
    // 當(dāng)前位置大于目標(biāo)位置,向左轉(zhuǎn)
    currentServoPos = max(currentServoPos - step, targetServoPos);
  }

  myServo.write(currentServoPos);  // 寫入新位置
  delay(15);  // 給舵機(jī)一點(diǎn)時(shí)間響應(yīng)
}

一種非阻塞式的控制思路,利用 loop() 的快速刷新特性實(shí)現(xiàn)了類似PID控制的緩啟緩?fù)PЧ?/p>

3.3風(fēng)扇控制算法

void controlFan(int speed, int direction) {
  // 限制速度在有效范圍 [0, 255]
  speed = constrain(speed, 0, FAN_MAX_SPEED);
  
  if (direction == 1) {
    // 反轉(zhuǎn): IA=0, IB=PWM
    setPWM(FAN_IA_PIN, 0);
    setPWM(FAN_IB_PIN, speed);
    fanDirection = 1;
  } 
  else if (direction == -1) {
    // 正轉(zhuǎn): IA=PWM, IB=0
    setPWM(FAN_IA_PIN, speed);
    setPWM(FAN_IB_PIN, 0);
    fanDirection = -1;
  } 
  else {
    // 停止: IA=0, IB=0
    setPWM(FAN_IA_PIN, 0);
    setPWM(FAN_IB_PIN, 0);
    fanDirection = 0;
  }
  
  fanSpeed = speed;
}

H橋驅(qū)動(dòng)原理

L9110內(nèi)部包含一個(gè)H橋電路,通過控制4個(gè)開關(guān)管實(shí)現(xiàn)電機(jī)正反轉(zhuǎn)

IA=HIGH, IB=LOW → 正轉(zhuǎn)IA=LOW, IB=HIGH → 反轉(zhuǎn)
IA=LOW, IB=LOW → 停止IA=HIGH, IB=HIGH → 剎車(不常用)

3.4 PWM定時(shí)器手動(dòng)配置

定時(shí)器工作原理

PWM頻率 = 時(shí)鐘頻率 / (預(yù)分頻系數(shù) × 重裝載值)
= 72MHz / (1 × 65535) ≈ 1098Hz

占空比 = 比較值 / 重裝載值 × 100%

// ============ PWM初始化 ============
void initPWMTimer() {
  Serial.println("[PWM] 初始化定時(shí)器...");
  
  // 配置引腳為PWM模式
  pinMode(FAN_IA_PIN, PWM);  // 引腳9 (PB7)
  pinMode(FAN_IB_PIN, PWM);  // 引腳5 (PB6)
  
  // 暫停定時(shí)器進(jìn)行配置
  Timer4.pause();
  
  // 設(shè)置PWM參數(shù)
  Timer4.setPrescaleFactor(1);     // 預(yù)分頻=1(不分頻)
  Timer4.setOverflow(65535);       // ARR=65535(16位最大)
  
  // 初始化比較值(占空比0%)
  Timer4.setCompare(TIMER_CH1, 0);  // CCR1=0 (引腳5)
  Timer4.setCompare(TIMER_CH2, 0);  // CCR2=0 (引腳9)
  
  // 刷新寄存器并啟動(dòng)定時(shí)器
  Timer4.refresh();
  Timer4.resume();
  
  Serial.println("[PWM] 定時(shí)器初始化完成");
}

// ============ PWM占空比設(shè)置 ============
void setPWM(int pin, uint8_t dutyCycle) {
  // 將0-255映射到0-65535
  uint16_t compareValue = (uint32_t)dutyCycle * 65535 / 255;
  
  if (pin == FAN_IA_PIN) {
    Timer4.setCompare(TIMER_CH2, compareValue);  // 引腳9
  } else if (pin == FAN_IB_PIN) {
    Timer4.setCompare(TIMER_CH1, compareValue);  // 引腳5
  }
}

參數(shù)說明

參數(shù) 含義 取值范圍 本項(xiàng)目設(shè)置
預(yù)分頻系數(shù) 時(shí)鐘分頻倍數(shù) 1-65536 1(不分頻)
重裝載值(ARR) 計(jì)數(shù)器最大值 1-65535 65535(最大分辨率)
比較值(CCR) 高電平持續(xù)計(jì)數(shù) 0-ARR 0-65535
占空比 CCR/ARR 0%-100% 用戶輸入0-255映射

3.5 完整代碼

/**************************************************************************************
 * 文件: /Gesture_Control_Servo_Fan/Gesture_Control_Servo_Fan.ino
 * 作者:零知實(shí)驗(yàn)室(深圳市在芯間科技有限公司)
 * -^^- 零知實(shí)驗(yàn)室,讓電子制作變得更簡(jiǎn)單! -^^-
 * 時(shí)間: 2025-12-30
 * 說明:零知標(biāo)準(zhǔn)板(STM32F103RBT6) + PAJ7620U2 + L9110 手勢(shì)控制系統(tǒng)
 * 功能:手勢(shì)控制舵機(jī)(12號(hào)引腳)和風(fēng)扇(5,9號(hào)引腳)
 *       向上-風(fēng)扇正轉(zhuǎn),向下-舵機(jī)90°,向左-舵機(jī)0°,向右-舵機(jī)180°
 *       順時(shí)針-風(fēng)扇正轉(zhuǎn),逆時(shí)針-風(fēng)扇反轉(zhuǎn),揮手-風(fēng)扇停止
 *       向前-風(fēng)扇加速,向后-風(fēng)扇減速
 ***************************************************************************************/

#include 
#include 
#include "RevEng_PAJ7620.h"

// 對(duì)象創(chuàng)建
RevEng_PAJ7620 sensor;
Servo myServo;

// 引腳定義
const int SERVO_PIN = 12;

// 風(fēng)扇引腳 - PB6(引腳5)和PB7(引腳9)對(duì)應(yīng)Timer4
const int FAN_IB_PIN = 5;     // PB6 - TIM4_CH1
const int FAN_IA_PIN = 9;     // PB7 - TIM4_CH2

// 系統(tǒng)參數(shù)
#define FAN_MIN_SPEED 80      // 風(fēng)扇最低啟動(dòng)速度
#define FAN_MAX_SPEED 255      // 風(fēng)扇最大速度
#define SPEED_STEP 175          // 每次調(diào)速的步長(zhǎng)

// 狀態(tài)變量
int currentServoPos = 90;      // 舵機(jī)當(dāng)前位置(角度)
int targetServoPos = 90;       // 舵機(jī)目標(biāo)位置(角度)
int fanSpeed = 0;              // 當(dāng)前風(fēng)扇速度(0-255)
int fanDirection = 0;          // 風(fēng)扇方向:0=停止,1=正轉(zhuǎn),-1=反轉(zhuǎn)

// 手勢(shì)檢測(cè)冷卻時(shí)間,防止重復(fù)觸發(fā)
unsigned long lastGestureTime = 0;
const unsigned long GESTURE_COOLDOWN = 500;  // 毫秒

bool systemReady = false;      // 系統(tǒng)是否就緒

// 系統(tǒng)狀態(tài)標(biāo)志
// ==================== 初始化函數(shù) ====================
void setup() {
  // 第1步:初始化串口通信
  initSerial();
  
  // 第2步:初始化I2C總線(PAJ7620傳感器需要)
  initI2C();
  
  // 第3步:初始化舵機(jī)
  initServo();
  
  // 第4步:初始化風(fēng)扇控制引腳
  initFan();
  
  // 第5步:初始化手勢(shì)傳感器
  initGestureSensor();
  
  // 第6步:顯示功能說明
  printFunctionMenu();
  
  // 第7步:系統(tǒng)就緒提示
  systemStartupComplete();
  
  systemReady = true;  // 標(biāo)記系統(tǒng)已就緒
}

// ==================== 主循環(huán)函數(shù) ====================
void loop() {
  unsigned long currentTime = millis();

  // 檢測(cè)手勢(shì)(帶冷卻時(shí)間,避免同一個(gè)手勢(shì)重復(fù)觸發(fā))
  if (currentTime - lastGestureTime > GESTURE_COOLDOWN) {
    Gesture gesture = sensor.readGesture();  // 讀取當(dāng)前手勢(shì)

    // 如果檢測(cè)到有效手勢(shì),則處理
    if (gesture != GES_NONE) {
      lastGestureTime = currentTime;  // 更新最后手勢(shì)時(shí)間
      handleGesture(gesture);         // 調(diào)用手勢(shì)處理函數(shù)
    }
  }

  // 平滑移動(dòng)舵機(jī)到目標(biāo)位置(每次循環(huán)移動(dòng)一小步)
  if (currentServoPos != targetServoPos) {
    moveServoSmoothly();
  }

  delay(50);  // 主循環(huán)延遲,不要太短以免CPU負(fù)擔(dān)過重
}

// ==================== PWM相關(guān)函數(shù) ====================

// 設(shè)置PWM占空比
void setPWM(int pin, uint8_t dutyCycle) {
  // 計(jì)算比較值:dutyCycle / 255 * overflow
  uint16_t compareValue = (uint32_t)dutyCycle * 65535 / 255;
  
  if (pin == FAN_IA_PIN) {
    // 引腳9 (PB7) 使用 Timer4 Channel2
    Timer4.setCompare(TIMER_CH2, compareValue);
  } 
  else if (pin == FAN_IB_PIN) {
    // 引腳5 (PB6) 使用 Timer4 Channel1
    Timer4.setCompare(TIMER_CH1, compareValue);
  }
}

// 初始化PWM定時(shí)器
void initPWMTimer() {
  Serial.println("[PWM] 初始化定時(shí)器...");
  
  // 配置引腳為PWM模式
  pinMode(FAN_IA_PIN, PWM);  // 引腳9 (PB7)
  pinMode(FAN_IB_PIN, PWM);  // 引腳5 (PB6)
  
  // 暫停定時(shí)器4進(jìn)行配置
  Timer4.pause();
  
  // 設(shè)置PWM參數(shù)
  // 72MHz / 1 / 65535 ≈ 1098Hz
  Timer4.setPrescaleFactor(1);     // 不分頻
  Timer4.setOverflow(65535);       // 16位最大分辨率
  
  // 初始化占空比為0(風(fēng)扇停止)
  Timer4.setCompare(TIMER_CH1, 0);  // 引腳5 (FAN_IB_PIN)
  Timer4.setCompare(TIMER_CH2, 0);  // 引腳9 (FAN_IA_PIN)
  
  // 刷新并啟動(dòng)定時(shí)器
  Timer4.refresh();
  Timer4.resume();
  
  Serial.println("[PWM] 定時(shí)器初始化完成 (引腳5=PB6/CH1, 引腳9=PB7/CH2)");
}

// ==================== 初始化函數(shù)詳細(xì)實(shí)現(xiàn) ====================

// 初始化串口通信
void initSerial() {
  Serial.begin(115200);
  delay(300);  // 等待串口穩(wěn)定
  
  Serial.println("n╔═══════════════════╗");
  Serial.println("║    零知實(shí)驗(yàn)室 - 手勢(shì)控制系統(tǒng) V2.0    ║");
  Serial.println("╚═══════════════════╝n");
  Serial.println("【系統(tǒng)初始化開始】n");
}

// 初始化I2C總線
void initI2C() {
  Serial.print("[1/5] I2C總線初始化...");
  Wire.begin();
  delay(100);
  Serial.println(" ?");
}

// 初始化舵機(jī)
void initServo() {
  Serial.print("[2/5] 舵機(jī)初始化...");
  
  myServo.attach(SERVO_PIN);
  myServo.write(currentServoPos);  // 設(shè)置初始位置90度
  delay(500);  // 等待舵機(jī)轉(zhuǎn)到初始位置
  
  Serial.print(" ? (初始位置: ");
  Serial.print(currentServoPos);
  Serial.println("°)");
}

// 初始化風(fēng)扇控制引腳
void initFan() {
  Serial.print("[3/5] 風(fēng)扇模塊初始化...");
  
  // 先初始化PWM定時(shí)器
  initPWMTimer();

  pinMode(LED_BUILTIN, OUTPUT);
  
  // 確保風(fēng)扇初始狀態(tài)為停止
  controlFan(0, 0);
  
  delay(200);
  Serial.println(" ? (狀態(tài): 停止)");
}

// 初始化PAJ7620手勢(shì)傳感器
void initGestureSensor() {
  Serial.println("[4/5] PAJ7620手勢(shì)傳感器初始化...");
  
  bool sensorInitialized = false;
  
  // 嘗試5次初始化
  for (int attempt = 1; attempt <= 5; attempt++) {
    Serial.print("      嘗試 ");
    Serial.print(attempt);
    Serial.print("/5...");
    
    if (sensor.begin()) {
      sensorInitialized = true;
      Serial.println(" ? 成功!");
      break;
    }
    
    Serial.println(" ? 失敗");
    delay(500);
  }

  // 如果初始化失敗,進(jìn)入錯(cuò)誤處理
  if (!sensorInitialized) {
    handleSensorInitError();
  }
}

// 傳感器初始化失敗處理
void handleSensorInitError() {
  Serial.println("n╔════════════════════╗");
  Serial.println("║         ? PAJ7620初始化失敗!         ║");
  Serial.println("╚════════════════════╝");
  Serial.println("n【故障排查清單】");
  Serial.println("  □ 1. 傳感器VCC是否接3.3V(不能接5V!)");
  Serial.println("  □ 2. GND是否正確接地");
  Serial.println("  □ 3. SDA和SCL引腳是否正確連接");
  Serial.println("  □ 4. 杜邦線接觸是否良好");
  Serial.println("  □ 5. 傳感器與開發(fā)板距離不要太遠(yuǎn)");
  Serial.println("  □ 6. 檢查傳感器是否損壞(聞是否有燒焦味)");
  Serial.println("n系統(tǒng)已停止運(yùn)行,請(qǐng)修復(fù)后重新上電。n");
  
  // LED快速閃爍表示錯(cuò)誤狀態(tài)
  while (1) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(50);
    digitalWrite(LED_BUILTIN, LOW);
    delay(50);
  }
}

// 顯示功能菜單
void printFunctionMenu() {
  Serial.println("[5/5] 系統(tǒng)配置加載... ?n");
  
  Serial.println("n========================================");
  Serial.println("           手勢(shì)功能說明");
  Serial.println("========================================");
  Serial.println("  向上   ↑  : 風(fēng)扇正轉(zhuǎn)啟動(dòng)");
  Serial.println("  向下   ↓  : 系統(tǒng)復(fù)位(舵機(jī)90°)");
  Serial.println("  向左   ←  : 舵機(jī)轉(zhuǎn)到0°");
  Serial.println("  向右   →  : 舵機(jī)轉(zhuǎn)到180°");
  Serial.println("  順時(shí)針 ?  : 風(fēng)扇正轉(zhuǎn)");
  Serial.println("  逆時(shí)針 ?  : 風(fēng)扇反轉(zhuǎn)");
  Serial.println("  揮手   ? : 風(fēng)扇停止");
  Serial.println("  向前   ?  : 風(fēng)扇加速");
  Serial.println("  向后   ?  : 風(fēng)扇減速");
  Serial.println("========================================n");
}

// 系統(tǒng)啟動(dòng)完成提示
void systemStartupComplete() {
  Serial.println("【系統(tǒng)初始化完成】n");
  
  // LED閃爍3次表示系統(tǒng)就緒
  for (int i = 0; i < 3; i++) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(150);
    digitalWrite(LED_BUILTIN, LOW);
    delay(150);
  }
  
  Serial.println("? 系統(tǒng)就緒,等待手勢(shì)輸入...n");
  Serial.println("═══════════════════════════════════════════n");
}

// ==================== 風(fēng)扇控制函數(shù) ====================
// 控制風(fēng)扇的轉(zhuǎn)速和方向
// speed: 速度值(0-255)
// direction: 方向(1=反轉(zhuǎn),-1=正轉(zhuǎn),0=停止)
void controlFan(int speed, int direction) {
  // 限制速度在有效范圍內(nèi)
  speed = constrain(speed, 0, FAN_MAX_SPEED);
  
  if (direction == 1) {
    // 反轉(zhuǎn):IA(引腳9)=0, IB(引腳5)=PWM
    setPWM(FAN_IA_PIN, 0);
    setPWM(FAN_IB_PIN, speed);
    fanDirection = 1;
  } 
  else if (direction == -1) {
    // 正轉(zhuǎn):IA(引腳9)=PWM, IB(引腳5)=0
    setPWM(FAN_IA_PIN, speed);
    setPWM(FAN_IB_PIN, 0);
    fanDirection = -1;
  } 
  else {
    // 停止:兩個(gè)引腳都輸出0
    setPWM(FAN_IA_PIN, 0);
    setPWM(FAN_IB_PIN, 0);
    fanDirection = 0;
  }
  
  fanSpeed = speed;
}

// 停止風(fēng)扇
void stopFan() {
  controlFan(0, 0);
  Serial.println("→ 風(fēng)扇: 已停止");
}

// 風(fēng)扇正轉(zhuǎn)
void fanForward() {
  // 如果當(dāng)前是停止?fàn)顟B(tài),使用最小速度啟動(dòng)
  if (fanDirection == 0) {
    fanSpeed = FAN_MIN_SPEED;
  }
  controlFan(fanSpeed, -1);
  Serial.print("→ 風(fēng)扇: 正轉(zhuǎn) | 速度: ");
  Serial.println(fanSpeed);
}

// 風(fēng)扇反轉(zhuǎn)
void fanReverse() {
  // 如果當(dāng)前是停止?fàn)顟B(tài),使用最小速度啟動(dòng)
  if (fanDirection == 0) {
    fanSpeed = FAN_MIN_SPEED;
  }
  controlFan(fanSpeed, 1);
  Serial.print("→ 風(fēng)扇: 反轉(zhuǎn) | 速度: ");
  Serial.println(fanSpeed);
}

// 風(fēng)扇加速
void fanSpeedUp() {
  // 只有在風(fēng)扇運(yùn)行時(shí)才能加速
  if (fanDirection != 0) {
    // 增加速度,但不超過最大值
    fanSpeed = constrain(fanSpeed + SPEED_STEP, FAN_MIN_SPEED, FAN_MAX_SPEED);
    controlFan(fanSpeed, fanDirection);  // 應(yīng)用新速度
    Serial.print("→ 風(fēng)扇: 加速至 ");
    Serial.println(fanSpeed);
  } else {
    Serial.println("? 提示: 請(qǐng)先啟動(dòng)風(fēng)扇(向上或順時(shí)針手勢(shì))");
  }
}

// 風(fēng)扇減速
void fanSpeedDown() {
  // 只有在風(fēng)扇運(yùn)行時(shí)才能減速
  if (fanDirection != 0) {
    // 降低速度,但不低于最小值
    fanSpeed = constrain(fanSpeed - SPEED_STEP, FAN_MIN_SPEED, FAN_MAX_SPEED);
    controlFan(fanSpeed, fanDirection);  // 應(yīng)用新速度
    Serial.print("→ 風(fēng)扇: 減速至 ");
    Serial.println(fanSpeed);
  } else {
    Serial.println("? 提示: 請(qǐng)先啟動(dòng)風(fēng)扇(向上或順時(shí)針手勢(shì))");
  }
}

// ==================== 舵機(jī)控制函數(shù) ====================
// 平滑移動(dòng)舵機(jī)(防止舵機(jī)快速轉(zhuǎn)動(dòng)時(shí)抖動(dòng)或損壞)
void moveServoSmoothly() {
  int step = 2;  // 默認(rèn)每次移動(dòng)2度

  // 根據(jù)目標(biāo)位置調(diào)整移動(dòng)步長(zhǎng)
  // 如果是移動(dòng)到0度或180度(左右手勢(shì)),使用較大步長(zhǎng)實(shí)現(xiàn)快速響應(yīng)
  if (targetServoPos == 0 || targetServoPos == 180) {
    step = 5;  // 大步長(zhǎng),快速移動(dòng)
  }

  // 根據(jù)當(dāng)前位置和目標(biāo)位置的關(guān)系,逐步移動(dòng)
  if (currentServoPos < targetServoPos) {
    // 當(dāng)前位置小于目標(biāo)位置,向右轉(zhuǎn)
    currentServoPos = min(currentServoPos + step, targetServoPos);
  } 
  else if (currentServoPos > targetServoPos) {
    // 當(dāng)前位置大于目標(biāo)位置,向左轉(zhuǎn)
    currentServoPos = max(currentServoPos - step, targetServoPos);
  }

  myServo.write(currentServoPos);  // 寫入新位置
  delay(15);  // 給舵機(jī)一點(diǎn)時(shí)間響應(yīng)
}

// ==================== 手勢(shì)處理函數(shù) ====================
void handleGesture(Gesture gesture) {
  Serial.print("? 檢測(cè)到手勢(shì): ");

  // 根據(jù)不同的手勢(shì)類型執(zhí)行相應(yīng)動(dòng)作
  switch (gesture) {
    case GES_UP:
      // 向上手勢(shì):?jiǎn)?dòng)風(fēng)扇正轉(zhuǎn)
      Serial.println("向上 ↑");
      fanForward();
      break;

    case GES_DOWN:
      // 向下手勢(shì):系統(tǒng)復(fù)位(舵機(jī)回中間,風(fēng)扇停止)
      Serial.println("向下 ↓");
      Serial.println("→ 執(zhí)行系統(tǒng)復(fù)位");
      targetServoPos = 90;  // 舵機(jī)回到90度中間位置
      // stopFan();            // 風(fēng)扇停止
      break;

    case GES_LEFT:
      // 向左手勢(shì):舵機(jī)轉(zhuǎn)到0度(最左側(cè))
      Serial.println("向左 ←");
      targetServoPos = 0;
      Serial.println("→ 舵機(jī): 轉(zhuǎn)向0°");
      break;

    case GES_RIGHT:
      // 向右手勢(shì):舵機(jī)轉(zhuǎn)到180度(最右側(cè))
      Serial.println("向右 →");
      targetServoPos = 180;
      Serial.println("→ 舵機(jī): 轉(zhuǎn)向180°");
      break;

    case GES_CLOCKWISE:
      // 順時(shí)針旋轉(zhuǎn)手勢(shì):風(fēng)扇正轉(zhuǎn)
      Serial.println("順時(shí)針 ?");
      fanForward();
      break;

    case GES_ANTICLOCKWISE:
      // 逆時(shí)針旋轉(zhuǎn)手勢(shì):風(fēng)扇反轉(zhuǎn)
      Serial.println("逆時(shí)針 ?");
      fanReverse();
      break;

    case GES_WAVE:
      // 揮手手勢(shì):停止風(fēng)扇
      Serial.println("揮手 ?");
      stopFan();
      break;

    case GES_FORWARD:
      // 向前推手勢(shì):風(fēng)扇加速
      Serial.println("向前 ?");
      fanSpeedUp();
      break;

    case GES_BACKWARD:
      // 向后拉手勢(shì):風(fēng)扇減速
      Serial.println("向后 ?");
      fanSpeedDown();
      break;

    default:
      // 未識(shí)別的手勢(shì)
      Serial.println("未識(shí)別的手勢(shì)");
      return;
  }

  // 顯示當(dāng)前系統(tǒng)狀態(tài)
  displayStatus();
  Serial.println("---");
}

// ==================== 狀態(tài)顯示函數(shù) ====================
void displayStatus() {
  Serial.print("


審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • STM32
    +關(guān)注

    關(guān)注

    2309

    文章

    11162

    瀏覽量

    373435
  • SG90
    +關(guān)注

    關(guān)注

    0

    文章

    10

    瀏覽量

    11744
  • L9110
    +關(guān)注

    關(guān)注

    3

    文章

    13

    瀏覽量

    17367
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    IDE——基于STM32F103RBT6的PAJ7620U2手勢(shì)控制WS2812 RGB燈帶系統(tǒng)

    簡(jiǎn)單! -^^- * 時(shí)間: 2025-12-26 * 說明: 基于標(biāo)準(zhǔn)(STM32F103RBT6)驅(qū)動(dòng)
    發(fā)表于 12-29 19:04

    IDE——基于標(biāo)準(zhǔn)驅(qū)動(dòng)PAJ7620U2手勢(shì)控制L9110風(fēng)扇模塊SG90舵機(jī)系統(tǒng)

    控制器,結(jié)合PAJ7620U2手勢(shì)傳感器實(shí)現(xiàn)對(duì)L9110風(fēng)扇模塊
    發(fā)表于 01-06 11:56

    控制舵機(jī)SG90的教程

    控制舵機(jī)SG90的教程一、SG90舵機(jī)常見的SG90舵機(jī)
    發(fā)表于 08-10 06:05

    手勢(shì)識(shí)別控制器制作

    目錄智能家居硬件小制作(含源碼)《手勢(shì)識(shí)別控制器》基于PAJ7620手勢(shì)模塊L298N
    發(fā)表于 09-07 06:45

    利用PAJ7620U2 Gesture Sensor手勢(shì)識(shí)別控制小車

    引言Arduino或ESP32驅(qū)動(dòng)小車作為一個(gè)經(jīng)典應(yīng)用,廣泛被開源硬件愛好者改裝。然而,其交互方式大部分依然是傳統(tǒng)的按鍵交互。本次嘗試改變Arduino 小車的交互方式,利用PAJ7620U2
    發(fā)表于 01-05 07:44

    手勢(shì)傳感PAJ7620U2的智能家居應(yīng)用分享

    1、手勢(shì)傳感PAJ7620U2的智能家居應(yīng)用  MM32F5270 是一款搭載了安謀科技 STAR-MC1 內(nèi)核的 MCU 產(chǎn)品,其工作頻率可達(dá) 120MHz,內(nèi)置多達(dá) 256KB Flash
    發(fā)表于 08-30 16:03

    【RA4M2設(shè)計(jì)挑戰(zhàn)賽】基于PAJ7620U2手勢(shì)識(shí)別網(wǎng)關(guān)設(shè)計(jì)

    1.簡(jiǎn)介基于瑞薩R7FA4M2AD3CFP進(jìn)行設(shè)計(jì),對(duì)接PAJ7620U2手勢(shì)識(shí)別模塊實(shí)現(xiàn)一款手勢(shì)識(shí)別網(wǎng)關(guān)。
    發(fā)表于 03-05 23:40

    使用Arduino和PAJ7620手勢(shì)傳感器制作手勢(shì)控制機(jī)器人

    使用Arduino和PAJ7620手勢(shì)傳感器制作手勢(shì)控制機(jī)器人,簡(jiǎn)單程序即可實(shí)現(xiàn)。小小的傳感器可以識(shí)別各種手勢(shì)。它采用內(nèi)置的空間傳感器,可以
    發(fā)表于 09-27 06:17

    ATK-PAJ7620手勢(shì)識(shí)別模塊的用戶手冊(cè)免費(fèi)下載

    PAJ7620U2 芯片,芯片內(nèi)部集成了光學(xué)數(shù)組式傳感器,以使復(fù)雜的手勢(shì)和光標(biāo)模式輸出,自帶九種手勢(shì)識(shí)別,支持上、下、左、右、前、后、順時(shí)針旋轉(zhuǎn)、逆時(shí)針旋轉(zhuǎn)和揮動(dòng)的手勢(shì)動(dòng)作識(shí)別,以
    發(fā)表于 03-13 08:00 ?62次下載
    ATK-<b class='flag-5'>PAJ7620</b><b class='flag-5'>手勢(shì)</b>識(shí)別<b class='flag-5'>模塊</b>的用戶手冊(cè)免費(fèi)下載

    PAJ7620U2集成I2C接口手勢(shì)識(shí)別傳感器的數(shù)據(jù)手冊(cè)免費(fèi)下載

    PAJ7620U2手勢(shì)識(shí)別功能與通用的I2C接口集成到一個(gè)芯片中。它可以識(shí)別9種手勢(shì),包括向上移動(dòng)、向下移動(dòng)、向左移動(dòng)、向右移動(dòng)、向前移動(dòng)、向后移動(dòng)、順時(shí)針旋轉(zhuǎn)、逆時(shí)針旋轉(zhuǎn)和波形。這
    發(fā)表于 03-13 08:00 ?85次下載
    <b class='flag-5'>PAJ7620U2</b>集成I<b class='flag-5'>2</b>C接口<b class='flag-5'>手勢(shì)</b>識(shí)別傳感器的數(shù)據(jù)手冊(cè)免費(fèi)下載

    微雪電子PAJ7620U2手勢(shì)傳感器簡(jiǎn)介

    PAJ7620U2 手勢(shì)識(shí)別模塊 I2C接口 可直接識(shí)別9種基本手勢(shì),支持手勢(shì)中斷輸出
    的頭像 發(fā)表于 01-02 15:20 ?2.1w次閱讀
    微雪電子<b class='flag-5'>PAJ7620U2</b><b class='flag-5'>手勢(shì)</b>傳感器簡(jiǎn)介

    PAJ7620U2帶I2C接口的集成手勢(shì)識(shí)別傳感器數(shù)據(jù)手冊(cè)免費(fèi)下載

    PAJ7620U2手勢(shì)識(shí)別功能與通用I2C接口集成到一個(gè)單片機(jī)上。可識(shí)別上移、下移、左移、右移、前、后、順時(shí)針、逆時(shí)針、波浪等9種手勢(shì)。這些手勢(shì)
    發(fā)表于 10-14 08:00 ?28次下載
    <b class='flag-5'>PAJ7620U2</b>帶I<b class='flag-5'>2</b>C接口的集成<b class='flag-5'>手勢(shì)</b>識(shí)別傳感器數(shù)據(jù)手冊(cè)免費(fèi)下載

    pwm控制SG90舵機(jī)資料分享

    pwm控制SG90舵機(jī)資料分享
    發(fā)表于 07-10 09:22 ?45次下載

    基于CW32的L9110風(fēng)扇模塊的應(yīng)用設(shè)計(jì)

    L9110風(fēng)扇模塊是一種常見的電機(jī)驅(qū)動(dòng)模塊,可以用于控制小型直流
    的頭像 發(fā)表于 08-31 14:44 ?2174次閱讀
    基于CW32的<b class='flag-5'>L9110</b><b class='flag-5'>風(fēng)扇</b><b class='flag-5'>模塊</b>的應(yīng)用設(shè)計(jì)

    IDE——基于STM32F103RBT6的PAJ7620U2手勢(shì)控制WS2812 RGB燈帶系統(tǒng)

    基于STM32F103RBT6的手勢(shì)控制LED系統(tǒng),通過PAJ7620U2傳感器識(shí)別手勢(shì)動(dòng)作,驅(qū)動(dòng)
    的頭像 發(fā)表于 12-29 17:48 ?1859次閱讀
    <b class='flag-5'>零</b><b class='flag-5'>知</b><b class='flag-5'>IDE</b>——基于STM32F103RBT6的<b class='flag-5'>PAJ7620U2</b><b class='flag-5'>手勢(shì)</b><b class='flag-5'>控制</b>WS2812 RGB燈帶<b class='flag-5'>系統(tǒng)</b>