Level1InterruptCause. How to fix?
Posted: Mon Feb 08, 2021 7:43 am
Hello,
I keep running into an issue using the NodeMCU 1.0 (ESP-12E), where the serial monitor outputs:
cause: 4 wdt reset
I am using 4 ultrasoundsensors, one in each corner next to a linear actuator, to determine the height of a desk, while it is being raised or lowered. If the actuators are out of sync, the fastest one should be stopped, until they are in sync again.
The same code doesn't crash on an arduino nano, it just doesn't fully work, as it doesn't have 6 Interrupt Pins.
What could be causing this issue?
Error:
Code:
I keep running into an issue using the NodeMCU 1.0 (ESP-12E), where the serial monitor outputs:
cause: 4 wdt reset
I am using 4 ultrasoundsensors, one in each corner next to a linear actuator, to determine the height of a desk, while it is being raised or lowered. If the actuators are out of sync, the fastest one should be stopped, until they are in sync again.
The same code doesn't crash on an arduino nano, it just doesn't fully work, as it doesn't have 6 Interrupt Pins.
What could be causing this issue?
Error:
Code: Select all
--- Serial monitor started ---
ets Jan 8 2013,rst cause:4, boot mode:(3,6)
wdt reset
load 0x4010f000, len 1392, room 16
tail 0
chksum 0xd0
csum 0xd0
v3d128e5c
~ld
Code:
Code: Select all
// Hardware: NodeMCU 1.0(12-E), 2x L298N, 4x HC-SR04 ultrasoundsensors, 4x linear actuator, 2x buttons
#define tINT 4 // Total number of sensors
#define soundSpeed 343.0 // Speed of sound in m/s
///// PINS //////////////////
#define RELAY1 10 // S3; RELAY1&2 for changing motor_direction. RELAY1 = HIGH && RELAY2 == LOW => raise
#define RELAY2 9 // S2; RELAY1 = LOW && RELAY2 = HIGH => lower
#define pwmFrontLeft 1 // TX
#define pwmBackRight 3 // RX
#define pwmBackLeft 15 // D8
#define pwmFrontRight 13 // D7
#define sensorFrontLeft 4 //D2
#define sensorBackLeft 2 //D4
#define sensorFrontRight 14 //D5
#define sensorBackRight 12 //D6
#define buttonUp 5 //D1 Switch 1
#define buttonDown 16 //D0 Switch 2
#define triggerPin 0 // D3; Pin number for the common trigger
volatile unsigned long travelTime[tINT]; // Place to store traveltime of the pusle
volatile unsigned long startTime[tINT]; // Place to store ping times (interrupt)
volatile bool new_measurement = false;
volatile int motor_direction = 0; // 0 = still, 1 = down, 2 = up, 3 = request pause
float distance[tINT]; // Calculated distances in cm
int lowest = 0; // height of lowest motor
int highest = 0; // height of highest motor
void ICACHE_RAM_ATTR handleSensorFrontRight();
void ICACHE_RAM_ATTR handleSensorFrontLeft();
void ICACHE_RAM_ATTR handleSensorBackRight();
void ICACHE_RAM_ATTR handleSensorBackLeft();
void ICACHE_RAM_ATTR handleButtonUp();
void ICACHE_RAM_ATTR handleButtonDown();
void ICACHE_RAM_ATTR commonSensorHandler(bool pinState, int nIRQ);
void ICACHE_RAM_ATTR handleButtonDownRising();
void ICACHE_RAM_ATTR handleButtonDownFalling();
void ICACHE_RAM_ATTR handleButtonUpRising();
void ICACHE_RAM_ATTR handleButtonUpFalling();
// PWM on arduino is 8-bit (0-253), on NodeMCU 10-bit(0-1023). Min 140-150, or stalling occurs.
int pwmFrontLeftUp = 245;
int pwmBackRightUp = 170;
int pwmBackLeftUp = 255;
int pwmFrontRightUp = 164;
// min pwm 130, they tend to stall with less
int pwmFrontLeftDown = 1023;
int pwmBackRightDown = 130;
int pwmBackLeftDown = 244;
int pwmFrontRightDown = 130;
/****************************************************************
SETUP
****************************************************************/
void setup()
{
Serial.begin(115200);
while (!Serial) {
; // Wait for Serial
}
Serial.println("--- Serial monitor started ---");
pinMode(triggerPin, OUTPUT); // common triggerpin
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
pinMode(pwmFrontLeft, OUTPUT);
pinMode(pwmBackRight, OUTPUT);
pinMode(pwmBackLeft, OUTPUT);
pinMode(pwmFrontRight, OUTPUT);
// Interrupt PINs
pinMode(sensorFrontLeft, INPUT);
pinMode(sensorBackLeft, INPUT);
pinMode(sensorFrontRight, INPUT);
pinMode(sensorBackRight, INPUT);
pinMode(buttonDown, INPUT_PULLUP);
pinMode(buttonUp, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonUp), handleButtonUp, CHANGE);
attachInterrupt(digitalPinToInterrupt(buttonDown), handleButtonDown, CHANGE);
attachInterrupt(digitalPinToInterrupt(sensorFrontLeft), handleSensorFrontLeft, CHANGE );
attachInterrupt(digitalPinToInterrupt(sensorBackLeft), handleSensorBackLeft, CHANGE );
attachInterrupt(digitalPinToInterrupt(sensorFrontRight), handleSensorFrontRight, CHANGE );
attachInterrupt(digitalPinToInterrupt(sensorBackRight), handleSensorBackRight, CHANGE );
}
/****************************************************************
LOOP
****************************************************************/
void loop()
{
if (motor_direction == 1) // turn backwards
{
Serial.println("backwards");
doMeasurement();
// set standard pwm values, then check if some of the motors should wait for slower motors (PWM=0)
int curPWM[4] = {pwmFrontLeftDown, pwmBackRightDown, pwmBackLeftDown, pwmFrontRightDown};
delayMicroseconds(10); // wait some time for measurement to complete
// look for highest motor, i.e. the slowest one
highest = 0; // assume slowest motor is index 0, then whether that's true
for (int i = 1; i < 5; i++)
{ if (distance[i] > distance[highest])
{
highest = i;
}
}
// if distance between two motors is above 1cm, pause the faster one
for (int i = 0; i < 5; i++)
{ if (distance[highest] - distance[i] > 1)
{
curPWM[i] = 0;
}
} // Set PWM speed
analogWrite(pwmFrontLeft, curPWM[0]);
analogWrite(pwmBackRight, curPWM[1]);
analogWrite(pwmBackLeft, curPWM[2]);
analogWrite(pwmFrontRight, curPWM[3]);
digitalWrite(RELAY1, LOW); // Turn relays to diff. signals to turn on all motors.
digitalWrite(RELAY2, HIGH);
}
else if (motor_direction == 2) // raise
{
Serial.println("raise");
doMeasurement();
int curPWM[4] = {pwmFrontLeftUp, pwmBackRightUp, pwmBackLeftUp, pwmFrontRightUp};
delayMicroseconds(10);
// Find lowest distance, i.e. slowest motor
lowest = 0;
for (int i = 1; i < 5; i++)
{ if (distance[i] < distance[lowest])
{
lowest = i;
}
}
// Pause motors that are more than 1cm ahead of the slowest one
for (int i = 0; i < 5; i++)
{ if (distance[i] - distance[lowest] > 1)
{
curPWM[i] = 0;
}
}
analogWrite(pwmFrontLeft, curPWM[0]);
analogWrite(pwmBackRight, curPWM[1]);
analogWrite(pwmBackLeft, curPWM[2]);
analogWrite(pwmFrontRight, curPWM[3]);
digitalWrite(RELAY1, HIGH);
digitalWrite(RELAY2, LOW);
}
else if (motor_direction == 3)
{ // time to pause the motors
Serial.println("stopping");
analogWrite(pwmFrontLeft, 0);
analogWrite(pwmBackRight, 0);
analogWrite(pwmBackLeft, 0);
analogWrite(pwmFrontRight, 0);
digitalWrite(RELAY2, LOW);
digitalWrite(RELAY1, LOW);
motor_direction = 0; // reset motor_direction
}
else {}
delayMicroseconds(50); // short break
}
/****************************************************************
Retrieve measurement and set next trigger
****************************************************************/
void doMeasurement()
{ // Send the trigger to calculate distances
digitalWrite(triggerPin, HIGH); // HIGH pulse for at least 10µs
delayMicroseconds(10);
digitalWrite(triggerPin, LOW); // Set LOW again
// Wait a bit then calculate distances
delayMicroseconds(20);
// First read will be 0 (no distance calculated yet)
// Read results. Pause interrupts to avoid corruption (having traveltime overwritten by interrupts while reading from it)
noInterrupts();
for (int i = 0; i < tINT; i++)
{
distance[i] = travelTime[i] / 2.0 * (float)soundSpeed / 10000.0; // in cm
}
interrupts();
// Initiate next trigger
// digitalWrite(triggerPin, LOW); // rest of loop already takes > 2µs
// delayMicroseconds(2);
}
/****************************************************************
INTERRUPT handling
****************************************************************/
void handleSensorFrontRight(void)
{
bool pinRead = digitalRead(sensorFrontRight);
commonSensorHandler(pinRead, 0);
}
void handleSensorFrontLeft(void)
{
bool pinRead = digitalRead(sensorFrontLeft);
commonSensorHandler(pinRead, 1);
}
void handleSensorBackLeft(void)
{
bool pinRead = digitalRead(sensorBackLeft);
commonSensorHandler(pinRead, 2);
}
void handleSensorBackRight(void)
{
bool pinRead = digitalRead(sensorBackRight);
commonSensorHandler(pinRead, 3);
}
// Common function for interrupts
void commonSensorHandler(bool pinState, int nIRQ)
{
unsigned long currentTime = micros(); // Get current time (in µs)
if (pinState)
{
startTime[nIRQ] = currentTime; // If pin state has changed to HIGH -> remember start time (in µs)
}
else
{
travelTime[nIRQ] = currentTime - startTime[nIRQ]; // If pin state has changed to LOW -> calculate time passed (in µs)
}
}
void handleButtonUp() { // When switch 1 is pressed
Serial.println("Button up pressed");
bool risingEdge = digitalRead(buttonUp);
if (risingEdge) {
handleButtonUpRising(); // signal goes LOW->HIGH, when button is released
}
else {
handleButtonUpFalling(); // Signal goes HIGH->LOW, when button is pressed
}
}
void handleButtonUpFalling() { // raise
motor_direction = 2;
}
void handleButtonUpRising() { // pause
motor_direction = 3;
}
void handleButtonDown() { // When switch 2 is pressed
bool risingEdge = digitalRead(buttonDown);
if (risingEdge) {
handleButtonDownRising();
}
else {
handleButtonDownFalling();
}
}
void handleButtonDownFalling() { // lower
motor_direction = 1;
}
void handleButtonDownRising() { // Beim loslassen pausieren anfragen
motor_direction = 3;
}
// END