首页 > 解决方案 > 交流调光器EpS32

问题描述

我有一个应用程序可以根据从温度传感器读取的温度来控制 ESP32 调光器。规则很简单,当我的传感器读取到超过 27ºC 的温度时,应通过调光器关闭灯。然而,这并没有发生。

代码所做的是,当系统打开时,灯会打开并时常读取温度,但当温度超过 27ºC 时,调光器不会关闭灯。我认为这可能是我在 zero_crosss_int 例程中做错的事情,因为当温度达到其极限时,会显示消息“TRIAC OFF”。

下面使用的代码。

#define     ZERO_CROSS          2
#define     DIMMER_CONTROL      4

int dimming=64;
float programedTemp = 27.0;
int halfDimming=128;
int maxDimming=64;


void power(void *parameters){
    tempSensor.requestTemperaturesByIndex(0);
    temp=tempSensor.getTempCByIndex(0);
    if(temp<programedTemp){
        dimming=maxDimming;
        if(temp<(programedTemp-1.0)){
            dimming=maxDimming;
        } else if(temp<programedTemp){
            dimming++;
        }
    } else if(temp>programedTemp+0.9){
        dimming=128;
    }else{
        dimming=halfDimming;
    }
    delay(4000);
}


void zero_crosss_int() {
    if(dimming>=128){
      delayMicroseconds(8.333);
      digitalWrite(DIMMER_CONTROL, LOW);    // triac Off
      Serial.println((String) "=====>>> TRIAC OFF <<<=====");
    }else{
        int dimtime = (65*dimming);
        delayMicroseconds(dimtime);    // Off cycle
        digitalWrite(DIMMER_CONTROL, HIGH);   // triac firing
        delayMicroseconds(8.333);
        digitalWrite(DIMMER_CONTROL, LOW);    // triac Off
    }
}

void setup() {
  pinMode(DIMMER_CONTROL, OUTPUT);
  pinMode(ZERO_CROSS, INPUT);
  attachInterrupt(ZERO_CROSS, zero_crosss_int, RISING);
  Serial.begin(115200);
  xTaskCreatePinnedToCore(power,"controlDimm",10000,NULL,0,&mainsPower,0);
}

void loop() {

}

标签: arduinoesp32

解决方案


您在中断处理程序中做太多了。令人惊讶的是,它不只是不断崩溃......没有发生的唯一原因可能是因为你没有在loop().

在中断处理程序中调用您正在调用的大多数函数是不安全的。中断处理程序需要运行尽可能短的时间——其他中断可能被锁定,它们可能会干扰网络堆栈和其他内务处理功能。您绝对不应该在中断处理程序中调用delayMicroseconds()或任何Serial方法,或者在那里花费超过绝对必要的时间。几乎所有 ESP-IDF 或 Arduino Core 函数都不能安全地从中断处理程序内部调用 - 中断处理程序可能会在它们处于不一致状态时中断对它们的另一个调用,或者可能会在它们处于中间状态时更改硬件设置使用该硬件。

如果您像这样构造它,您的代码会更好:

volatile bool zero_crossing_flag = false;

void IRAM_ATTR zero_cross_int() {
  zero_crossing_flag = true;
}

void loop() {
  if(zero_crossing_flag) {
    zero_crossing_flag = false;

    if(dimming>=128){
      delayMicroseconds(8.333);
      digitalWrite(DIMMER_CONTROL, LOW);    // triac Off
      Serial.println((String) "=====>>> TRIAC OFF <<<=====");
    }else{
        int dimtime = (65*dimming);
        delayMicroseconds(dimtime);    // Off cycle
        digitalWrite(DIMMER_CONTROL, HIGH);   // triac firing
        delayMicroseconds(8.333);
        digitalWrite(DIMMER_CONTROL, LOW);    // triac Off
    }
  }
}

IRAM_ATTRon 属性zero_cross_int()告诉编译器该代码必须始终可用。如果你编写一个没有IRAM_ATTR它的中断处理程序,如果它正确执行基本上是幸运的。

以这种方式重构你的代码可能不会解决你所问的问题,但它会允许它以一种稳定的、可重现的方式运行,这不太可能是现在编写的方式。


推荐阅读