
/**比特树创造力【BIT.SH1003多功能智能风扇板卡全功能验证】
1、能够根据接收到的红外遥控器数字按键值0-3改变风速,同时在数码管上显示0-3数字风速档位;
2、能够根据接收到的红外遥控器按键值(齿轮键0xFFA857)或实体按键1(D4)在不同的工作模式切换;
3、工作模式1蜂鸣器响1声为红外遥控模式;
4、工作模式2蜂鸣器响2声为超声波测距模式,距离越远,风速越快,(<5cm=0档、<30cm=1档、<60cm=2档、>60cm=3档)数码管显示相应档位;
5、工作模式3蜂鸣器响3声为温湿度自动调速模式,当温湿度越高风速越大;
5、工作模式4蜂鸣器响4声为手动调速模式,结合A3引脚电位器映射风扇转速;
6、实体按键SW1和SW2按下有不同声音;
7、所有操作能够通过A1引脚的蜂鸣器不同声音次数反馈;
bit-tree.com by liking [2025-07-25]
**/
#include <IRremote.h> // 红外遥控库
#include <Wire.h> // IIC通信库,用于AHT20温湿度传感器
// ======================================
// 硬件引脚与参数定义区
// ======================================
/** 引脚定义 **/
#define BEEPER A1 // 有源蜂鸣器控制引脚
#define IR_RECEIVE_PIN 7 // 红外接收模块引脚
#define TRIG_PIN 2 // 超声波传感器触发引脚
#define ECHO_PIN 3 // 超声波传感器回声引脚
#define FAN_NEG 6 // 风扇电机负极控制引脚
#define FAN_POS 5 // 风扇电机正极PWM控制引脚
#define SW1 4 // 实体按键1(模式切换)
#define SW2 A2 // 实体按键2(保留音效)
#define POT A3 // 手动调速模式电位器引脚
/** 数码管引脚定义 **/
#define SEG_A A0 // 数码管A段
#define SEG_B 8 // 数码管B段
#define SEG_C 9 // 数码管C段
#define SEG_D 10 // 数码管D段
#define SEG_E 11 // 数码管E段
#define SEG_F 12 // 数码管F段
#define SEG_G 13 // 数码管G段
/** 红外遥控器按键码定义 **/
#define FAN_0 0xFF6897 // 0档风速对应红外码
#define FAN_1 0xFF30CF // 1档风速对应红外码
#define FAN_2 0xFF18E7 // 2档风速对应红外码
#define FAN_3 0xFF7A85 // 3档风速对应红外码
#define MODE_SWITCH 0xFFA857 // 模式切换按键(齿轮键)对应红外码
/** 工作模式定义 **/
#define MODE_IR 1 // 模式1:红外遥控模式(蜂鸣器响1声)
#define MODE_ULTRASONIC 2 // 模式2:超声波测距模式(蜂鸣器响2声)
#define MODE_TEMP_HUM 3 // 模式3:温湿度自动模式(蜂鸣器响3声)
#define MODE_MANUAL 4 // 模式4:手动调速模式(蜂鸣器响4声)
/** AHT20温湿度传感器参数 **/
#define AHT20_ADDR 0x38 // AHT20的IIC通信地址
#define AHT20_INIT_CMD 0xBE // AHT20初始化命令
#define AHT20_MEASURE_CMD 0xAC // AHT20测量命令
/** 蜂鸣器音效参数 **/
#define BEEP_DURATION 100 // 单声持续时间(毫秒)
#define BEEP_GAP 100 // 声音之间的间隔(毫秒)
// ======================================
// 全局变量定义区
// ======================================
int currentMode = MODE_IR; // 当前工作模式(初始化为红外遥控模式)
int modeSpeeds[5] = {0}; // 各模式独立保存的风速档位
unsigned long modeTimers[5] = {0}; // 各模式定时计数器
unsigned long debounceDelay = 200; // 按键去抖延迟(毫秒)
float humidity = 0.0; // 湿度值(百分比)
float temperature = 0.0; // 温度值(摄氏度)
bool isPlaying = false; // 蜂鸣器播放状态标志
// 红外接收对象
IRrecv irrecv(IR_RECEIVE_PIN);
decode_results results;
// 数码管段码表(共阴极,0-3)
const byte digitPatterns[4][7] = {
{1, 1, 1, 1, 1, 1, 0}, // 0
{0, 1, 1, 0, 0, 0, 0}, // 1
{1, 1, 0, 1, 1, 0, 1}, // 2
{1, 1, 1, 1, 0, 0, 1} // 3
};
// ======================================
// 蜂鸣器控制函数区
// ======================================
/**
控制有源蜂鸣器开关
@param on true=发声,false=停止
*/
void setBuzzer(bool on) {
digitalWrite(BEEPER, on ? HIGH : LOW);
}
/**
播放指定次数的提示音
@param count 发声次数
*/
void playBeepSequence(int count) {
if (isPlaying || count < 1) return;
isPlaying = true;
for (int i = 0; i < count; i++) {
setBuzzer(true);
delay(BEEP_DURATION);
setBuzzer(false);
if (i < count - 1) delay(BEEP_GAP);
}
isPlaying = false;
}
/**
播放模式切换提示音
@param mode 模式编号(1-4),响对应次数
*/
void playModeTone(int mode) {
playBeepSequence(mode);
}
/**
按键2(SW2)的音效
播放1声短音
*/
void playButton2Sound() {
if (isPlaying) return;
isPlaying = true;
setBuzzer(true);
delay(BEEP_DURATION);
setBuzzer(false);
isPlaying = false;
}
/**
红外操作反馈音
播放短提示音
*/
void playIRFeedback() {
if (isPlaying) return;
isPlaying = true;
setBuzzer(true);
delay(BEEP_DURATION / 2);
setBuzzer(false);
isPlaying = false;
}
// ======================================
// 传感器控制函数区
// ======================================
/**
初始化AHT20温湿度传感器
@return 成功返回true,失败返回false
*/
bool initAHT20() {
Wire.beginTransmission(AHT20_ADDR);
Wire.write(AHT20_INIT_CMD);
Wire.write(0x08);
Wire.write(0x00);
if (Wire.endTransmission() != 0) return false;
delay(100);
return true;
}
/**
读取AHT20温湿度数据
*/
void readAHT20() {
Wire.beginTransmission(AHT20_ADDR);
Wire.write(AHT20_MEASURE_CMD);
Wire.write(0x33);
Wire.write(0x00);
Wire.endTransmission();
delay(80);
if (Wire.requestFrom(AHT20_ADDR, 6) != 6) return;
byte status = Wire.read();
if ((status & 0x80) == 0) {
byte hum1 = Wire.read();
byte hum2 = Wire.read();
byte hum3 = Wire.read();
byte temp1 = Wire.read();
byte temp2 = Wire.read();
byte temp3 = Wire.read();
unsigned long humValue = ((unsigned long)hum1 << 12) |
((unsigned long)hum2 << 4) |
(hum3 >> 4);
humidity = humValue * 100.0 / 0x100000;
unsigned long tempValue = ((unsigned long)(hum3 & 0x0F) << 16) |
((unsigned long)temp1 << 8) |
temp2;
temperature = tempValue * 200.0 / 0x100000 - 50;
}
}
/**
超声波测距
@return 距离(厘米)
*/
long getDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH);
return constrain(duration * 0.0343 / 2, 0, 150);
}
// ======================================
// 模式控制函数区
// ======================================
/**
红外遥控模式逻辑
*/
void runIRMode() {}
/**
超声波模式逻辑(每500ms更新)
*/
void runUltrasonicMode() {
if (millis() - modeTimers[MODE_ULTRASONIC] < 500) return;
long distance = getDistance();
int newSpeed = distance < 5 ? 0 :
(distance < 30 ? 1 :
(distance < 60 ? 2 : 3));
if (newSpeed != modeSpeeds[MODE_ULTRASONIC]) {
modeSpeeds[MODE_ULTRASONIC] = newSpeed;
setFanSpeed(newSpeed);
}
modeTimers[MODE_ULTRASONIC] = millis();
}
/**
温湿度模式逻辑(每2000ms更新)
*/
void runTempHumMode() {
if (millis() - modeTimers[MODE_TEMP_HUM] < 2000) return;
readAHT20();
float tempIndex = constrain((temperature - 20) / 20, 0, 1);
float humIndex = constrain(humidity / 100, 0, 1);
float index = (tempIndex * 0.6 + humIndex * 0.4) * 100;
int newSpeed = index < 25 ? 0 : (index < 50 ? 1 : (index < 75 ? 2 : 3));
if (newSpeed != modeSpeeds[MODE_TEMP_HUM]) {
modeSpeeds[MODE_TEMP_HUM] = newSpeed;
setFanSpeed(newSpeed);
}
modeTimers[MODE_TEMP_HUM] = millis();
}
/**
手动模式逻辑(每200ms更新)
*/
void runManualMode() {
if (millis() - modeTimers[MODE_MANUAL] < 200) return;
int newSpeed = map(analogRead(POT), 0, 1023, 0, 3);
if (newSpeed != modeSpeeds[MODE_MANUAL]) {
modeSpeeds[MODE_MANUAL] = newSpeed;
setFanSpeed(newSpeed);
}
modeTimers[MODE_MANUAL] = millis();
}
// ======================================
// 设备控制函数区
// ======================================
/**
设置风扇风速
@param speed 风速档位(0-3)
*/
void setFanSpeed(int speed) {
if (speed < 0 || speed > 3) return;
int pwmValue = speed * 85; // 0→0, 1→85, 2→170, 3→255
digitalWrite(FAN_NEG, LOW);
analogWrite(FAN_POS, pwmValue);
}
/**
数码管显示数字
@param digit 数字(0-3)
*/
void displayDigit(int digit) {
if (digit < 0 || digit > 3) return;
digitalWrite(SEG_A, digitPatterns[digit][0]);
digitalWrite(SEG_B, digitPatterns[digit][1]);
digitalWrite(SEG_C, digitPatterns[digit][2]);
digitalWrite(SEG_D, digitPatterns[digit][3]);
digitalWrite(SEG_E, digitPatterns[digit][4]);
digitalWrite(SEG_F, digitPatterns[digit][5]);
digitalWrite(SEG_G, digitPatterns[digit][6]);
}
// ======================================
// 事件处理函数区
// ======================================
/**
处理红外命令
@param cmd 红外码值
*/
void processIRCommand(unsigned long cmd) {
switch (cmd) {
case FAN_0:
modeSpeeds[currentMode] = 0;
setFanSpeed(0);
playIRFeedback();
break;
case FAN_1:
modeSpeeds[currentMode] = 1;
setFanSpeed(1);
playIRFeedback();
break;
case FAN_2:
modeSpeeds[currentMode] = 2;
setFanSpeed(2);
playIRFeedback();
break;
case FAN_3:
modeSpeeds[currentMode] = 3;
setFanSpeed(3);
playIRFeedback();
break;
case MODE_SWITCH:
switchMode(); // 红外模式切换
break;
}
}
/**
模式切换函数(循环切换)
*/
void switchMode() {
currentMode = (currentMode % 4) + 1; // 1→2→3→4→1
setFanSpeed(modeSpeeds[currentMode]);
playModeTone(currentMode); // 播放模式提示音
}
/**
检查按键状态
SW1改为模式切换,SW2保留音效
*/
void checkButtons() {
static unsigned long lastDebounce = 0;
unsigned long now = millis();
// SW1按键:模式切换(带防抖)
if (digitalRead(SW1) == LOW && now - lastDebounce > debounceDelay) {
switchMode(); // 执行模式切换
lastDebounce = now;
}
// SW2按键:保留原有音效
if (digitalRead(SW2) == LOW && now - lastDebounce > debounceDelay) {
playButton2Sound();
lastDebounce = now;
}
}
// ======================================
// 初始化与主循环区
// ======================================
void setup() {
// 初始化引脚
pinMode(BEEPER, OUTPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(FAN_POS, OUTPUT);
pinMode(FAN_NEG, OUTPUT);
pinMode(SW1, INPUT_PULLUP); // 模式切换按键
pinMode(SW2, INPUT_PULLUP); // 音效按键
pinMode(POT, INPUT);
// 初始化数码管
pinMode(SEG_A, OUTPUT);
pinMode(SEG_B, OUTPUT);
pinMode(SEG_C, OUTPUT);
pinMode(SEG_D, OUTPUT);
pinMode(SEG_E, OUTPUT);
pinMode(SEG_F, OUTPUT);
pinMode(SEG_G, OUTPUT);
// 初始化通信
Serial.begin(9600);
Wire.begin();
irrecv.enableIRIn();
// 初始化AHT20
if (!initAHT20()) {
Serial.println("AHT20初始化失败!");
while (1);
}
// 初始化定时器
for (int i = 1; i <= 4; i++) modeTimers[i] = millis();
// 初始状态
setBuzzer(false);
setFanSpeed(0);
displayDigit(0);
playModeTone(MODE_IR); // 启动提示
}
void loop() {
// 处理红外信号
if (irrecv.decode(&results) && !isPlaying) {
processIRCommand(results.value);
irrecv.resume();
}
// 检查按键(SW1模式切换,SW2音效)
checkButtons();
// 执行当前模式逻辑
if (!isPlaying) {
switch (currentMode) {
case MODE_IR: runIRMode(); break;
case MODE_ULTRASONIC: runUltrasonicMode(); break;
case MODE_TEMP_HUM: runTempHumMode(); break;
case MODE_MANUAL: runManualMode(); break;
}
displayDigit(modeSpeeds[currentMode]);
}
delay(50);
}