我正在尝试制作一个在 ESP32 上运行的带有中断的代码,但我总是得到一个 Guru Meditation
Guru Meditation Error:Core 1 panic'ed(CPU1 上的中断 wdt 超时)。 核心 1 寄存器转储: PC:0x4008e6b4 PS:0x00060c35 A0:0x8008d64e A1:0x3ffbefac
A2:0x3ffb8a00 A3:0x3ffb8890 A4:0x00000004 A5:0x00060c23
A6:0x00060c23 A7:0x00000001 A8:0x3ffb8890 A9:0x00000018
A10:0x3ffb8890 A11:0x00000018 A12:0x3ffc42d4 A13:0x00060c23
A14:0x007bf158 A15:0x003fffff SAR:0x0000000e 借口:0x00000006
EXCVADDR:0x00000000 LBEG:0x40089c09 LEND:0x40089c19 LCOUNT:0xfffffffc
Core 1 在 ISR 上下文中运行: EPC1:0x400dffeb EPC2:0x00000000 EPC3:0x00000000 EPC4:0x00000000 回溯:0x4008e6b1:0x3ffbefac |<-CORRUPTED Core 0 register dump: PC : 0x4008e833 PS : 0x00060035 A0 : 0x8008d277 A1 : 0x3ffbeaac
A2 : 0x3ffbf158 A3
我使用的是 Arduino IDE 2.1.0,所以我无法使用异常解码器。这是我的代码,它仍在进行中。
#include <Wire.h>
#include <AS5600.h>
#include <WiFi.h>
#include <esp_now.h>
#define HES 19
#define LimitPins 18
#define TCA9548A_ADDR 0x70
#define N17AS5600 3
#define N23AS5600 2
#define AS5600_ADDR 0x36
volatile bool HESstate = true;
volatile bool LastHESState = true;
volatile int Count = 0;
volatile bool LimiteState = true;
volatile bool LastLimitState = true;
volatile bool N17Direction = false;
volatile int MainLoop = 1;
volatile int StartValue;
volatile int StopValue;
volatile int DistanceN17;
volatile long LastButtonPress = 0;
volatile bool FirstTimeN17 = false;
volatile bool HomeZeroN17 = false;
volatile bool GetTimeN17 = false;
volatile bool FirstTimeN23 = false;
volatile bool HomeZeroN23 = false;
int16_t Angle17;
int16_t Angle23;
int32_t Distance17;
int32_t Distance23;
int32_t OffsetD17;
int32_t OffsetD23;
AS5600 SensorN17;
AS5600 SensorN23;
uint8_t broadcastAddress[] = {0xC8, 0xF0, 0x9E, 0xA6, 0x08, 0xF0};
typedef struct struct_message {
int MSG;
} struct_message;
struct_message myData;
esp_now_peer_info_t peerInfo;
void TCA9548A(byte bus){
if(bus > 7) return;
Wire.beginTransmission(TCA9548A_ADDR);
Wire.write(1 << bus);
Wire.endTransmission();
}
void SetupInterrupts(){
pinMode(HES, INPUT_PULLUP);
attachInterrupt(HES, HallEffectSensor, FALLING);
pinMode(LimitPins, INPUT_PULLUP);
attachInterrupt(LimitPins, LimitSwitches, RISING);
}
void SetupTCA9548A(){
TCA9548A(N17AS5600);
SensorN17.begin(21, 22); // .begin(sda, scl) pour ESP32
TCA9548A(N23AS5600);
SensorN23.begin(21, 22); // .begin(sda, scl) pour ESP32
OffsetD23 = -1 * SensorN23.getCumulativePosition();
}
void SetupESP_NOW(){
WiFi.mode(WIFI_STA);
if(esp_now_init() != ESP_OK){
Serial.println("Error initializing ESP-NOW");
return;
}
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if(esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
}
void setup() {
Serial.begin(9600);
Wire.begin();
SetupInterrupts();
SetupTCA9548A();
SetupESP_NOW();
delay(5000);
}
void loop() {
if(MainLoop == 1){
myData.MSG = 170; // 170: Nema17 va UP.
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
MainLoop = 11;
while(GetTimeN17){
Serial.print("Temps: ");
Serial.print(StopValue - StartValue);
Serial.print(" | Vitesse: ");
Serial.println(DistanceN17 / (StopValue - StartValue));
}
}
if(MainLoop == 2){
myData.MSG = 171; // 171: Nema17 va DOWN.
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
MainLoop = 22;
if(!FirstTimeN17){
StartValue = millis();
FirstTimeN17 = true;
}
}
if(MainLoop == 9){
myData.MSG = 179; // 170: Nema17 à l'arrêt.
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
MainLoop = 11;
if(!HomeZeroN17){
OffsetD17 = -1 * SensorN17.getCumulativePosition();
HomeZeroN17 = true;
MainLoop = 2;
}
}
//LastHESState = true;
LastLimitState = true;
}
void HallEffectSensor(){
/*if(LastHESState){
if(!N23Homed){
myData.MSG = 239; // 239: Nema23 à l'arrêt.
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
N23Homed = true;
}
//HESstate = !HESstate;
LastHESState = false;
}*/
}
void LimitSwitches(){
if(LastLimitState){
switch(MainLoop){
case 11:
MainLoop = 9;
case 22:
MainLoop = 1;
StopValue = millis();
DistanceN17 = SensorN17.getCumulativePosition();
GetTimeN17 = true;
default:
MainLoop = 0;
}
LastLimitState = false;
}
}
我尝试编写的代码是当我从引脚 18 和 19 获得外部触发器时,(我知道引脚 19 中断部分已全部注释),变量 MainLoop 更改它的值以访问特定部分主循环。
感谢那些会看看我的问题的人。晚安
你的代码至少有两个主要问题。
首先,必须使用属性
IRAM_ATTR
定义中断处理程序。这迫使系统将它们保存在内存中。因为中断处理程序对时间非常敏感,所以系统无法像其他代码那样按需从闪存中读取它们。
所以
void HallEffectSensor(){
应该是
void IRAM_ATTR HallEffectSensor(){
和
void LimitSwitches(){
应该是
void IRAM_ATTR LimitSwitches(){
其次,您在中断处理程序中做way太多的工作。
中断完全按照他们所说的去做。它们 interrupt 您的代码流 - 不可预测。这意味着它们可以在您的代码操纵数据结构或控制硬件时中断您的代码,并且当中断处理程序运行时,数据结构或硬件控制器可能处于不一致状态。或者中断处理程序可以在不为人知的情况下更改程序中其他地方的指令之间的状态。
中断处理程序尽快返回也很重要,以便可以处理其他中断。
您的中断处理程序
HallEffectSensor()
调用 esp_now_send()
,这几乎可以保证使系统崩溃。它可以在已经运行的情况下轻松进入 ESP-NOW 协议栈。你无法知道esp_now_send()
的实现是什么;除非 ESP-IDF 明确表示从中断处理程序调用是安全的,否则你一定不要从中断处理程序调用它,除非你真的希望你的程序崩溃。
同样,您的中断处理程序
LimitSwitches()
调用 SensorN17.getCumulativePosition()
从中断处理程序调用几乎肯定也不安全。
相反,除非您真的知道自己在做什么,否则您应该让每个中断处理程序将一个
volatile boolean
变量设置为true
以指示中断发生,然后在loop()
中检查变量是否为true
并在那里完成工作。有更复杂的方法可以做到这一点,但它们都不涉及从实际的中断处理程序调用这些函数。
您的程序中可能存在其他问题,但除非您解决这些问题,否则它肯定无法可靠运行。