You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过GPIO AC调光器实现AC风扇调速?(XIAO ESP32S3调试问题)

AC风扇调速失效问题排查与修复方案

问题背景

使用Seeed XIAO ESP32S3作为主控,D2引脚连接AC调光器的过零检测(Z-C)引脚,D3引脚连接调光控制引脚。目前风扇仅能以0或100%转速运行,调速功能失效。因RBDDimmer.h库报错过多,已弃用该库,现有两段代码:一段可运行但仅支持二元调速,另一段完全无法执行。

现有代码问题分析

第一段代码(仅二元调速)

这段代码的核心逻辑错误在于:直接用analogWrite控制AC调光引脚,且硬编码输出固定电平,完全未利用过零检测实现导通角控制。AC负载调速不能使用普通PWM,必须配合过零信号调整导通角,否则只能实现全关或全开。

代码片段:

const int zeroCrossPin = D2; // Zero-cross pin
const int adcPin = D3;       // AC dimmer control pin

void acdimmer(int pm25)
{
  Serial.print("Adjusting fan speed based on PM2.5: ");
  Serial.println(pm25);

  if (pm25 < 15) {
    fan = 40; // Very low fan speed
  } 
  else if (pm25 >= 15 && pm25 < 30) {
    fan = 60; // Low fan speed
  } 
  else {
    fan = 100; // Maximum fan speed
  }

  // acd.setPower(fan); // Set power 0 to 100% 
  // int actualPower = acd.getPower(); // Fetch the power level the dimmer is applying
  analogWrite(adcPin, 10);
  Serial.print("Fan Speed Set To: ");
  Serial.print(fan);
  Serial.print("% (Actual Power: ");
  Serial.print(100);
  Serial.println("%)");
}

第二段代码(完全无法运行)

这段代码的调速逻辑方向正确,但存在多个致命问题:

  • 引脚号错误:XIAO ESP32S3的D2/D3引脚不能直接用数字2/3代替,中断绑定引脚错误导致过零检测失效。
  • 延时计算错误:50Hz市电半周期为10000μs,dimming*65的换算逻辑完全偏离,延时超出有效范围,触发信号无效。
  • 变量竞态问题:volatile变量dimming在loop中直接赋值,未做临界区保护,可能导致中断与主程序的数据冲突。
  • 初始化错误:AC调光不需要analogWrite初始化,应直接设置引脚为LOW电平。

代码片段:

#include <Arduino.h>

// Pin Definitions
const int zeroCrossPin = 2; // Zero-crossing detection pin
const int dimmerPin = 3;   // Dimmer control pin (PWM output)

volatile int dimming = 128; // Initial dimming level (0-255 for PWM duty cycle)
volatile bool zeroCross = false; // Zero-crossing detected flag

void zeroCrossHandler() {
  zeroCross = true; // Set zero-cross flag on interrupt
}

void setup() {
  // Initialize serial monitor for debugging
  Serial.begin(9600);
  Serial.println("Fan Speed Control Initialized");

  // Initialize pins
  pinMode(zeroCrossPin, INPUT);
  pinMode(dimmerPin, OUTPUT);
  
  // Attach interrupt for zero-cross detection
  attachInterrupt(digitalPinToInterrupt(zeroCrossPin), zeroCrossHandler, RISING);

  // Start with fan off
  analogWrite(dimmerPin, 0);
  Serial.println("Dimmer initialized.");
}

void loop() {
  // Example: Read an analog value (0-1023) and map it to dimming level (0-255)
  int sensorValue = analogRead(A0); // Assume a potentiometer connected to A0
  dimming = map(sensorValue, 0, 1023, 0, 255);

  // Debugging output
  Serial.print("Sensor Value: ");
  Serial.print(sensorValue);
  Serial.print(" -> Dimming Level: ");
  Serial.println(dimming);

  // Adjust fan speed if zero-cross detected
  if (zeroCross) {
    zeroCross = false; // Reset zero-cross flag
    delayMicroseconds(dimming * 65); // Delay proportional to dimming level
    digitalWrite(dimmerPin, HIGH); // Trigger triac gate
    delayMicroseconds(10); // Allow time for triac to latch
    digitalWrite(dimmerPin, LOW); // Turn off gate signal
  }
}

修复后的完整代码

针对XIAO ESP32S3特性,修正引脚映射、延时计算和变量问题,整合PM2.5调速逻辑:

#include <Arduino.h>

// XIAO ESP32S3 引脚定义
const int zeroCrossPin = D2; // 过零检测引脚
const int dimmerPin = D3;    // 调光控制引脚(触发双向可控硅)

volatile bool zeroCrossDetected = false;
volatile uint8_t powerLevel = 0; // 0-100% 功率等级

// 中断函数需放在RAM中执行(ESP32S3要求)
void IRAM_ATTR zeroCrossISR() {
  zeroCrossDetected = true;
}

void setup() {
  Serial.begin(115200);
  
  pinMode(zeroCrossPin, INPUT_PULLUP); // 启用上拉适配过零模块输出
  pinMode(dimmerPin, OUTPUT);
  digitalWrite(dimmerPin, LOW);
  
  // 绑定过零上升沿中断
  attachInterrupt(digitalPinToInterrupt(zeroCrossPin), zeroCrossISR, RISING);
  
  Serial.println("AC Fan Speed Control Ready");
}

// 设置风扇功率(0-100%)
void setFanPower(uint8_t power) {
  powerLevel = constrain(power, 0, 100);
}

void loop() {
  // 替换为实际PM2.5传感器读取代码
  int pm25 = random(0, 50); // 临时用随机值模拟
  Serial.print("PM2.5 Value: ");
  Serial.println(pm25);
  
  // 根据PM2.5值调整功率
  if (pm25 < 15) {
    setFanPower(40);
  } else if (pm25 >= 15 && pm25 < 30) {
    setFanPower(60);
  } else {
    setFanPower(100);
  }
  Serial.print("Set Fan Power: ");
  Serial.print(powerLevel);
  Serial.println("%");
  
  // 处理过零触发逻辑
  if (zeroCrossDetected) {
    zeroCrossDetected = false;
    
    if (powerLevel == 0) {
      digitalWrite(dimmerPin, LOW);
      return;
    }
    
    // 50Hz市电半周期10000μs,功率越低延时越长(导通越晚)
    unsigned int delayUs = map(powerLevel, 0, 100, 10000, 0);
    delayMicroseconds(delayUs);
    
    // 触发可控硅
    digitalWrite(dimmerPin, HIGH);
    delayMicroseconds(10); // 保持触发信号足够时长
    digitalWrite(dimmerPin, LOW);
  }
  
  delay(1000); // 每秒更新一次PM2.5数据
}

关键修复点说明

  1. 引脚修正:使用XIAO ESP32S3官方引脚标识D2/D3,确保中断和引脚模式设置正确。
  2. 中断优化:中断函数添加IRAM_ATTR属性,满足ESP32S3对高频中断函数的内存要求。
  3. 延时计算:基于50Hz市电半周期(10000μs),将0-100%功率映射为10000-0μs的延时,功率越低导通越晚,输出功率越小。
  4. 硬件适配:过零检测引脚启用INPUT_PULLUP,适配多数AC过零模块的集电极开路输出。
  5. 功率保护:用constrain限制功率值在0-100%范围,0%时直接关闭触发信号。

额外注意事项

  • 确保AC调光器的过零检测信号为3.3V兼容电平,若为5V输出需添加分压电阻。
  • 可控硅触发引脚需串联100-220Ω限流电阻,避免烧毁开发板引脚。
  • 调试时可使用示波器观察过零信号与触发信号的时序,确认延时和触发时机是否正确。

内容的提问来源于stack exchange,提问作者RIDDHIDIPTA PAL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:04:52