You go to sleep unconditionally in every iteration of loop()
. That's not what you want. The way your code is now, you'll miss every wake up event that happens while your normal program code runs.
Your code spends most of the time delaying inside flash()
. And the controller goes to sleep after flash()
is done. Always. This means that whenever a wake up event occurrs while the LED is flashing, it will not cause a wake up. That's just because the interrupt occurred and was serviced before you went to sleep.
Have a look at the example in the avr-libc docs here.
Your code should look like this:
void loop(){
cli(); // Disable interrupts to avoid race condition.
if ( !resetEsp ) {
// Only go to sleep if we have nothing to do right now.
// Safe(*) code from the example in avr-libc:
sleep_enable();
sei();
sleep_cpu();
sleep_disable();
} else {
sei(); // Can go on processing IRQs.
}
if (resetEsp) {
cli();
resetEsp = false; // clear the flags
resetEnabled = false;
sei();
digitalWrite(pinRST, LOW); // reset the ESP
delayMicroseconds(240);
digitalWrite(pinRST, HIGH); // let the ESP Boot
flash(10, 50); // flash the led fast to show we're waking the ESP
} else if (resetEnabled) {
flash(10, 500); // mostly never get here
} else {
flash(2, 500); // these are the flashes I see most of the time
}
}
The point here is that we disable all interrupts while we check to see if we want to go to sleep. This way, we make sure that no interrupt can happen after we checked but before we actually sleep.
Is is crucial, however, that we enable interrupts again just before going to sleep, or we will never be woken up again.
Also, @jms is right in stating that you have another potential race codition when resetting your flags, so include some cli/sei there too.
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
can go into setup()
. And if you're not controlling spacecraft the same goes for sleep_enable();
, while omitting sleep_disable();
completely.
(*) The code labelled "safe" above is not absolutely bullet-proof because, in theory, during optimization the compiler could decide to reorder some instructions so that sei()
and sleep_cpu()
could end up not being in direct sequence. To be absolutely safe, check the generated assembler code (gcc -save-temps
), or just write the reqired instructions as inline assembler yourself. (Can be as simple as asm volatile (" sei \r\n sleep \r\n " :::);
.)
Here's a slightly different approach in stead of a Lua vs. Python shootout:
Six of the most popular ESP8266 "runtimes":
- AT Command SET. Popular when the 8266 is paired with another MCU.
Communicates via the serial port. ~64k of 128k RAM available.
- MicroPython. A MicroPython script interpreter
with user friendly GUI that can be accessed via the serial
port or WIFI/IP. ~30k of 128k RAM available.
- Lua/NodeMCU. A LUA script interpreter with user friendly GUI that
can be accessed via the serial port. ~40k of 128k RAM available.
- JavaScript/Espruino. A JavaScript interpreter with user friendly
GUI that can be acess via the serial port or WiFi/IP. ~20k of 128k RAM available.
- C/IDE-12E. ESP8266 flashing tool & C libraries/tools using the standard Arduino IDE. ~80k of 128k RAM available.
- C/ESP8266_SDK. C libraries/tools from the manufacturer. Also a collection
of example applications. ~512k Flash. Guesstimate 80k of 128k
RAM available.
The key insight is that the bulk of the code is common. The primary libraries in 1-5 all originate from 6. Beneath a thin layer of AT/Python/LUA/JavaScript/C the primary code is practically identical. That means performance (RAM, FLASH, execution) is similar too.
Since you seem concerned about speed and RAM (flash is generally OK) how about option #5? Arduino is a usable IDE with a large collection of examples. You could have your first code running in less than an hour and would likely outperform any of the scripting engines.
In the absence of significant memory usage differences I would choose MicroPython due to the greater number of libraries and an active online community with IRC webchat. Documentation for adding C modules has improved.
Option #6 provides you with the highest potential for optimization but at higher complexity and steeper learning curve.
Lastly a good ESP8266 rule-of-thumb: Each TCP/IP connection can consume up to ~3k of memory. Always expect less than 5 simultaneous connections!
TL;DR: ESP8266 applications have most of their code in common and perform similarly. So choose the script engine you like or step up to C/IDE-12E. Don't expect more than 5 simultaneous IP connections.
Best Answer
Invert the RI signal of the SIM808 so you will have a rising edge at the ESP8266's pin when RI goes low. You can use a couple of resistors and a NMOSFET.
simulate this circuit – Schematic created using CircuitLab
When RI is high the WAKEUP pin will be on ground, if RI goes high then WAKEUP will be pulled up to VCC through R2. Here is a simulation, you can click on the left "L/H" to switch the input level.