arduino - 交流调光器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() {
}
解决方案
您在中断处理程序中做的太多了。令人惊讶的是,它不只是不断崩溃......没有发生的唯一原因可能是因为你没有在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
on 属性zero_cross_int()
告诉编译器该代码必须始终可用。如果你编写一个没有IRAM_ATTR
它的中断处理程序,如果它正确执行基本上是幸运的。
以这种方式重构你的代码可能不会解决你所问的问题,但它会允许它以一种稳定的、可重现的方式运行,这不太可能是现在编写的方式。
推荐阅读
- microsoft-graph-api - pathIsTooLong 不是从 createUploadSession api 返回的
- oracle - 如何使用具有多值的 Oracle 的 LISTAGG 函数?
- python - 如何在 SimpleElastix 中重用 ImagePyramids?
- php - 一般错误:Laravel 5.6.33 中的“)”附近的 1:语法错误“)
- java - 使用流或集合对对象内的列表进行排序
- wordpress - WooCommerce、wordpress 搜索、pre_get_posts 过滤器排除摘录和产品描述
- angular - Angular:删除http调用中的重复元素
- javascript - 谷歌图表仪表不显示,TypeError: google.visualization.Gauge is not a constructor
- node.js - swagger 工具是否只使用 json 格式
- node.js - 我需要一种方法让 Kafka 消费者提交特定消息