我有一个应用程序,可以从温度传感器读取的温度来控制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() {
}
答案 0 :(得分:0)
您在中断处理程序中做的太多了。令人惊讶的是,它不仅持续崩溃,而且没有发生的唯一原因很可能是因为您在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_ATTR
上的zero_cross_int()
属性告诉编译器该代码必须始终可用。如果您编写的中断处理程序不带IRAM_ATTR
,那么它可以正确执行基本上是幸运的。
以这种方式重组代码可能无法解决您所要解决的问题,但可以使它以稳定,可重复的方式运行,这与现在编写的方式不太可能。
答案 1 :(得分:0)
使用您的ZCD输入生成中断。在ISR中,启动一个计时器,该计时器会在ZCD中断的0ms(全功率)到10ms(完全关闭)之间生成另一个中断。
我不明白要关掉灯,为什么要用TRIAC代替继电器。