0

Would like to ask for assistance. Tried several routes. My knowledge is lacking and unable to progress further. I think I am very close to the solution (maybe couple of lines of codes away), but the answer seems to lie in the memory state of the ESP32 after coming back from "deep sleep". The code is not that difficult so you may want to skip to "the problem" section below to spare you the details. Thank you!!!

The Arduino program is a marriage of two separate Arduino programs (attached), both work. One program is deep sleep with ext0 (and/or ext1) wake interrupt on which I got off the web. The other program measures the time difference between two separate LOW or FALLING signals on Pin 12 and 27 of the ESP32 SparkFun Thing Plus. The signals come on both pins and drop fast (about 20-40ns) and are about 200-800 micro-seconds apart in duration. They always come in pairs and randomly seconds or minutes apart.

How it supposed to work: The first LOW/FALLING signal is always on pin 12 and the second LOW/FALLING always on pin 27. A single LOW/FALLING signal on pin12 wakes up the ESp32 from deep sleep using the ext0 wake up event and an attach interrupt with ISR. The ISR runs a micros() routine that takes a snapshot of the "time1" when the interrupt happened. It stores that value. Next the second LOW/FALLING signal happens on pin27 within about 200-800 micro-seconds from the first one on pin12. It does another ISR routine and takes a snapshot of the "time2" of the second signal (on pin27). A routine subtracts "time2" - "time1" to arrive to the final value. Once that is done, the ESp32 goes back to sleep.

The problem: Both separate programs work. This combined program works but only for every second set of readings. There is some sort of a deep sleep-wake-up issue which I think is that either not all input pins are usable for a period of time after wake-up from deep sleep. Even if I am using the ext0 which keeps some of the peripherals (pin12 and pin27 included) active during sleep. Or maybe there is a problem with keeping the measured time value(s) in memory after sleep. When I send a LOW signal to pin 12 , I get a wake-up triggered by pin12 via ext0 and the SR records the" time1" timestamp. But then it hangs there as the second incoming signal on pin27 does nothing with or without ext1 and using attachinterrupt with ISR.

After the first pair of external signals with the ESP32 fully wake but hanging on pin27, I run again the pair of LOW signals to pin12 and pin 27 (200-600 micro-seconds apart from each other). At this time both ISRs work and I get a correct final value of " time2-time1", AND the Esp32 also goes back to deep sleep. If I repeat the process, the same thing happens with pin12 waking up the ESp32 but pin27 just hangs there until I run the second set of signals again a few seconds later.

What I tried: I used ext0 for pin12 wake up with attachinterrupt. Since ext0 uses the RTC Peripherals, I do not think I need to use a pin definition from RTC Preph to GPOI Digital designation ( esp_err_t rtc_gpio_deinit(GPIO_NUM_12). For the second interrupt singal on pin 27, I cannot use ext0 anymore, so I used ext1. This does not have any power during deep sleep and when it wakes up it has to have its RTC Peripherials statyus changed to GPIO status using esp_err_t rtc_gpio_deinit(GPIO_NUM_27); and then attacheinterrupt to it.

I suspect that somehow the second signal on pin27 does not register after deep sleep. I tried to use these commands in various combinations on pin 12 and pin27and the ISRs to save the data during/after deep sleep, but no avail:

RTC_DATA_ATTR ; IRAM_ATTR ; dettachinterrupt, esp_err_t rtc_gpio_deinit(GPIO_NUM_27);

If I had two ext0 wakeup pin options, I think I would not run into this problem. Or if ext1 could be woken up fast enough (less than 200 micro-seconds) so its usable as an interrupt, it would also work. Ultimately, I may need to use the ULP coprocessor to run the time measurement while the ESP32 deep sleeps. The goal is to be able to run this setup on deep sleep instead of using 80-100 mAh.



/*
Deep Sleep with External Wake Up
=====================================
This code displays how to use deep sleep with
an external trigger as a wake up source and how
to store data in RTC memory to use it over reboots

This code is under Public Domain License.

Hardware Connections
======================
NOT USED: Push Button to GPIO 33 pulled down with a 10K Ohm
resistor

NOTE:
======
Only RTC IO can be used as a source for external wake
source. They are pins: 0,2,4,12-15,25-27,32-39.

Modified code...   Original deep sleep code by Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/

#include <Arduino.h>
#include <FunctionalInterrupt.h>
#include "esp_deep_sleep.h"
#include <driver/gpio.h>
#include <DeepSleepScheduler.h>


//#define BUTTON_PIN_BITMASK 0x1000 // 2^12 in hex

unsigned long time1=0;
unsigned long time2=0;


RTC_DATA_ATTR int bootCount = 0;

volatile boolean Flag = false; //trigger 1 happened
/////////////////////////////////////////////////////////////////////////////
/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}
/////////////// END OF WAKE UP REASON//////////////////////////////////////////////////////////

void isr(){
  time1 = micros();
Flag = true;
    Serial.print("Time1  ");Serial.println(time1);
 }   //////////////////// end of ISR routine pin12 //////////////////////////////
 
   void isr2(){
    time2= micros();
      if (Flag == true)  {
        Serial.print("Time2  ");Serial.println(time2);
       Serial.print("Time2-Time1    ");Serial.println(time2-time1);
        Flag = false;
        time1=0;
        time2=0;

        //Go to sleep now routine ////////////////////////////////////////////////////
     Serial.println("Going to sleep now in 10 m-sec");
    delay(1);
    esp_deep_sleep_start();
    Serial.println("This will never be printed");
 
      }
}     ///end of ISR2 routine pin27 incl. CONDITIONAL DEEP SLEEP ROUTINE//////


void setup(){
  pinMode(12, INPUT_PULLUP);
  pinMode(27, INPUT_PULLUP);
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  /*
  First we configure the wake up source
  We set our ESP32 to wake up for an external trigger.
  There are two types for ESP32, ext0 and ext1 .
  ext0 uses RTC_IO to wakeup thus requires RTC peripherals
  to be on while ext1 uses RTC Controller so doesnt need
  peripherals to be powered on.
  Note that using internal pullups/pulldowns also requires
  RTC peripherals to be turned on.
  */
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_12,0); //1 = High, 0 = Low/  
                 //no hardware pull up/down. Feeding ext. HIGH to LOW signal
                                                                             
isr();  // duplicated in attachinterrupt below...?

       attachInterrupt(digitalPinToInterrupt(12), isr, FALLING); //rearm interrupt1


esp_sleep_enable_ext1_wakeup(GPIO_SEL_27, ESP_EXT1_WAKEUP_ALL_LOW);  
// no hardware connections or pull op/down, feeding
                                                                                                                      //Feeding ext. HIGH to LOW signal
   attachInterrupt(digitalPinToInterrupt(27), isr2, FALLING); //rearm interrupt2


}     ////  END OF SETUP and TWO EXT INTERRUPTS //////////////////////

void loop(){
  //This is not going to be called
}
  • I don't read all the text, so I might miss something. If you intent to measure the time delta of two signals from two different sources, you could combine them with an OR-gate and attach the output to pin 12. Then attach the second sig. to pin 27 also. You need only one interrupt (ext0 on pin12) and read pin 27 to see if it is caused by the second signal (pin27 == HIGH) or the first (pin27 == LOW). I you want to exclude that both signals are HIGH use a XOR-gate instead of a OR-gate. That only works if the second sig. is long enough to be measured, of cause. – Peter Paul Kiefer Nov 20 '19 at 9:37
  • If the signals are LOW active, you have to use inverted gates and triggering on a rising edge. And OR-gates can be simulated by diodes, if you have no logic ICs at hand. – Peter Paul Kiefer Nov 20 '19 at 9:43
  • Thank you for the suggestion about the OR or XOR gates. It would be a smart (hardware) solution to remedy the ESP32's inherent limitations of slow wake-up-interrupt. It would get around the unresponsive ext1 pin (pin27 in this case) and would use only the working interrupt pin (pin12), to register both consecutive LOW signals (in this case FALLING) signals aout 200-600 micro-secs apart. – TommyS Nov 22 '19 at 2:12
  • I need to come up with a few lines of code that would store the timestamp value of Signal 1 until the timestamp value of Signal 2 (on the same pin thanks to the XOR/OR gate) was read using the micros(). Then delta the two time-stamp values to get the desired final number. – TommyS Nov 22 '19 at 2:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.