I'm trying to do stuff in the loop with an external interrupt running. Delaying causes weird crashes...
Hardware: ESP-12f
Core Version: 2.3.0
I get a crash from Exception(0) if I use delay(>0) inside the loop with my external interrupt running. Oddly, delay(0) and delayMicroseconds(1000) don't cause a crash.
Module: Generic ESP8266 Module
Flash Size: 4MB/1MB
CPU Frequency: 80Mhz
Flash Mode: dio
Flash Frequency: 40Mhz
Upload Using: SERIAL
Reset Method: Hardware (button)
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
//Pin setup
const int zeroPin = 12;
const int lightPin = 13;
//Timing setup
long triggerDelay = 7300;
//Dimming vars
long prevZeroMicros = 0;
//Pulsing vars
long newVal = 2350;
//boolean rising = true;
void setup() {
pinMode(zeroPin, INPUT);
pinMode(lightPin, OUTPUT);
digitalWrite(lightPin, HIGH);
Serial.begin(115200);
attachInterrupt(digitalPinToInterrupt(zeroPin), dimmerCross, RISING);
}
void loop() {
/*if(rising) newVal++;
else newVal--;
if(newVal>=7300) rising = false;
else if(newVal<=2350) rising = true;
else triggerDelay = newVal;
delay(2);*/
//delay(0);//works fine
delay(1);//crashes after a little while (~20 sec from upload completion)
//delayMicroseconds(1000);//works fine
}
void dimmerCross() {
noInterrupts();
if(micros()-prevZeroMicros > 6000) {//Check for accidental triggers
dimm();
prevZeroMicros = micros();
}
interrupts();
}
void dimm() {
delayMicroseconds(triggerDelay);
digitalWrite(13, HIGH);
delayMicroseconds(400);
digitalWrite(13, LOW);
}
Exception (0):
epc1=0x40201c90 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: sys
sp: 3ffffc30 end: 3fffffb0 offset: 01a0
>>>stack>>>
3ffffdd0: 40106b58 80be5999 fffffff0 3ffee2b8
3ffffde0: ffffffff 00000020 40240000 fffffe1a
3ffffdf0: 00000006 00000006 42da0000 00000022
3ffffe00: 3fffc200 40106b20 3fffc258 4000050c
3ffffe10: 400043a3 00000030 00000016 ffffffff
3ffffe20: 60000200 00000002 7c097c08 80000000
3ffffe30: 20000000 3fff09d8 80000000 203fc180
3ffffe40: 00000000 3fffc6fc 3ffee538 3fff09dc
3ffffe50: 00000174 003fc180 60000600 00000030
3ffffe60: 7fffffff 3ffe951c 3ffe951c 40201cba
3ffffe70: 40106bbc 3ffee2b8 00000000 40106ba6
3ffffe80: ffffffff 00000020 3fff0004 00000000
3ffffe90: 00000000 00000000 0000001f 40105139
3ffffea0: 4000050c 40106b20 3fffc258 4000050c
3ffffeb0: 40000f68 00000030 00000017 ffffffff
3ffffec0: 40000f58 00000000 00000020 00000000
3ffffed0: feefeffe 3ffee538 3ffee538 fffffffe
3ffffee0: ffffffff 3ffede38 3ffee538 3fffdab0
3ffffef0: 00000000 3fffdad0 3ffee6b0 00000030
3fffff00: 00000000 400042db 00000064 60000600
3fffff10: 40004b31 3fff0854 000002f4 003fc000
3fffff20: 4010569e 3ffede60 3ffecf00 40106d58
3fffff30: 40206f59 3ffecf00 3ffede60 02aaca2a
3fffff40: 3fff0854 00001000 402073ee 00000008
3fffff50: 00000000 00000000 4020749b 3ffecfb4
3fffff60: 3ffede60 0083e9ab 3ffede60 60000600
3fffff70: 40218b81 3ffecfb4 3ffede60 02aac843
3fffff80: 40218bc6 3fffdab0 00000000 3fffdcb0
3fffff90: 3ffede88 3fffdad0 3ffee6b0 402026cb
3fffffa0: 40000f49 000180b6 3fffdab0 40000f49
<<<stack<<<
ets Jan 8 2013,rst cause:2, boot mode:(1,7)
0x40106b58: interrupt_handler at /root/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/core_esp8266_wiring_digital.c line 119
0x40106b20: interrupt_handler at /root/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/core_esp8266_wiring_digital.c line 113
0x40201cba: dimmerCross() at /media/deb/HDD/Documents/Arduino/sketch_jul12b/sketch_jul12b.ino line 52
0x40106bbc: interrupt_handler at /root/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/core_esp8266_wiring_digital.c line 135
0x40106ba6: interrupt_handler at /root/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/core_esp8266_wiring_digital.c line 131
0x40105139: ets_timer_disarm at ?? line ?
0x40106b20: interrupt_handler at /root/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/core_esp8266_wiring_digital.c line 113
0x4010569e: spi_flash_read at ?? line ?
0x40106d58: pvPortZalloc at /root/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/heap.c line 33
0x40206f59: pm_set_sleep_time at ?? line ?
0x402073ee: pm_get_sleep_type at ?? line ?
0x4020749b: pm_get_sleep_type at ?? line ?
0x40201018: delay_end at /root/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/core_esp8266_wiring.c line 40
0x40218b81: ets_timer_handler_isr at ?? line ?
0x40218bc6: ets_timer_handler_isr at ?? line ?
0x402026cb: loop_task at /root/.arduino15/packages/esp8266/hardware/esp8266/2.3.0/cores/esp8266/core_esp8266_main.cpp line 56
using delay in the interrupt handler is not a good idea, even though it's a short one.
Here is a sketch that I and other users worked on a while back for zero cross dimming:
https://gist.github.com/me-no-dev/2e185a909000f6ac9605
Non-Blocking and no delays
@me-no-dev can you suggest schematic for your ZeroCrossTriac.ino sketch
I did not make the device :) maybe @larsenglund can help, but AFAIK it's a pretty standard approach. ZeroCross on GPIO4 and the triac connected to GPIO5
@me-no-dev your missing loop function means we could have our specific loop? how it could implemented for dimming purpose
the sketch runs async, so all you need to do in your loop logic is control the period variable to change the dim level
Thanks, I'll take a look at your code. Still doesn't explain my crashes though...
ISR handler has to be marked with ICACHE_RAM_ATTR.
Well, I modified your code for 60Hz just to see if it would work off the bat but no luck. I'll see if I can do more testing and merge both a bit...
Well, that was an easy fix! My code works fine if you just add the ICACHE_RAM_ATTR to my ISR, thanks igrr! Do you know why that's needed? I don't see it mentioned in any ESP8266 or Arduino documentation... I'll probably continue with me-no-dev's way though, as it frees up more processor time.
Modified me-no-dev's dimmer code:
//Dimmer defs
#define TRIAC_PIN 13
#define ZERO_CROSS_PIN 12
#define DEBOUNCE_TIME 6000 //9ms - 10ms is the pulse period
//Dimmer vars
static uint32_t lastPulse = 0;
static uint16_t period = 7000; //5ms - 50% for each half wave
static bool high = false;
void ICACHE_RAM_ATTR onTimerISR(){
if(high){//OUTPUT is HIGH
digitalWrite(TRIAC_PIN, LOW);
high = false;
} else {
digitalWrite(TRIAC_PIN, HIGH);
high=true;
timer1_write(400*5);
}
}
void ICACHE_RAM_ATTR onPinISR(){
uint32_t now = micros();
if(now - lastPulse < DEBOUNCE_TIME) return;
lastPulse = now;
timer1_write(period * 5);
}
void setup(){
Serial.begin(115200);
pinMode(TRIAC_PIN, OUTPUT);
pinMode(ZERO_CROSS_PIN, INPUT);
digitalWrite(TRIAC_PIN, LOW);
timer1_attachInterrupt(onTimerISR);
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE);
attachInterrupt(digitalPinToInterrupt(ZERO_CROSS_PIN), onPinISR, RISING);
}
long newVal = 2350;
boolean rising = true;
void loop(){
if(rising) newVal++;
else newVal--;
if(newVal>=7300) rising = false;
else if(newVal<=2350) rising = true;
else period = newVal;
delay(1);
}
It is needed because ISR can come at any time, for example when flash cache
is disabled. There's an open ticket in this issue tracker about documenting
ICACHE_RAM_ATTR requirement.
On Sat, Jul 16, 2016, 03:38 david476 [email protected] wrote:
Well, that was an easy fix! My code works fine if you just add the
ICACHE_RAM_ATTR to my ISR, thanks igrr! Do you know why that's needed? I
don't see it mentioned in any ESP8266 or Arduino documentation... I'll
probably continue with me-no-dev's way though, as it frees up more
processor time.Modified me-no-dev's dimmer code:
//Dimmer defs
define TRIAC_PIN 13
define ZERO_CROSS_PIN 12
define DEBOUNCE_TIME 6000 //9ms - 10ms is the pulse period
//Dimmer vars
static uint32_t lastPulse = 0;
static uint16_t period = 7000; //5ms - 50% for each half wave
static bool high = false;void ICACHE_RAM_ATTR onTimerISR(){
if(high){//OUTPUT is HIGH
digitalWrite(TRIAC_PIN, LOW);
high = false;
} else {
digitalWrite(TRIAC_PIN, HIGH);
high=true;
timer1_write(400*5);
}
}void ICACHE_RAM_ATTR onPinISR(){
uint32_t now = micros();
if(now - lastPulse < DEBOUNCE_TIME) return;
lastPulse = now;
timer1_write(period * 5);
}void setup(){
Serial.begin(115200);
pinMode(TRIAC_PIN, OUTPUT);
pinMode(ZERO_CROSS_PIN, INPUT);
digitalWrite(TRIAC_PIN, LOW);
timer1_attachInterrupt(onTimerISR);
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE);
attachInterrupt(digitalPinToInterrupt(ZERO_CROSS_PIN), onPinISR, RISING);
}long newVal = 2350;
boolean rising = true;void loop(){
if(rising) newVal++;
else newVal--;if(newVal>=7300) rising = false;
else if(newVal<=2350) rising = true;
else period = newVal;delay(1);
}—
You are receiving this because you commented.Reply to this email directly, view it on GitHub
https://github.com/esp8266/Arduino/issues/2284#issuecomment-233050942,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AEJcenAXSi-zKam9qdYwdKePhdNf1DsJks5qV-G8gaJpZM4JNB-5
.
@igrr do you know link or documents which is well described specification and application of ICACHE_xx_ATTR terms ? by the way it is good example of timer's functions in actual sketch, hope find more example
How do I use this code with 2 lamps?
I tried to duplicate the void ICACHE_RAM_ATTR onTimerISR_1 () and void ICACHE_RAM_ATTR onTimerISR_2 () but unsuccessfully
Most helpful comment
ISR handler has to be marked with ICACHE_RAM_ATTR.