Help with ESP8266 + DS3231 + 555 Timer Project

Hi All,

I'm getting stuck on the final piece of my project and I could use some help! I've gone through old posts on this forum, stackexchange, and github as well as tried to troubleshoot the problem myself but still haven't figured this problem out. I'm hoping someone out there can point me in the right direction.

So I have a project that incorporates an ESP8266 (ESP), a real time clock (RTC) and a motion sensor (PIR). The ESP runs some code then goes into Light Sleep mode. It wakes up whenever motion is sensed. This successfully works since the the PIR emits a HIGH pulse on its output pin and the following line (from the Espressif documentation) allows a for a pin on the ESP to look for a HIGH pulse while it's in Light Sleep:

gpio_pin_wakeup_enable(GPIO_ID_PIN(12), GPIO_PIN_INTR_HILEVEL)

//Note: the pin can look for a LOW pulse like so '...GPIO_PIN_INTRLOLEVEL)

Now I no longer want to wake up the ESP from motion. Instead I want it to wake up at a specific time each day, do its thing, then go back to sleep. So I’ve swapped out my RTC for a DS3231 RTC which has alarm functions. Using JChristensens DS3232RTC library, I’m able to set an alarm and enable the SQW/INT pin (on the RTC) to output a pulse when the alarm is asserted. For now, the alarm is asserted once every minute. The SQW/INT pin is active low so I have a 10k pull-up resistor on it. (I’ve verified this using a simple ISR to set a flag and check for that flag).

So I thought it would be as easy as connecting the SQW/INT pin to the input pin (pin 12) on my ESP and adjust the code to look for a LOW pulse:

gpio_pin_wakeup_enable(GPIO_ID_PIN(12), GPIO_PIN_INTR_LOLEVEL)

As it turns out, the SQW/INT pin outputs something closer to a falling edge signal and not a true LOW pulse. What makes me think this? Well again, by using a simple ISR that runs on a falling edge, I’m able to see the flag being set before the ESP goes to sleep. But once asleep, the ESP never wakes up. So it can see the falling edge but not the LOW pulse.

Okay, so how can I get a signal closer to 0v (or Vcc), right? Well I thought one way of doing that would be to incorporate a 555 timer. With a 555 in monostable mode, it will detect the falling edge from the SQW/INT pin and output a HIGH pulse for a second or two. Effectively converting my falling edge signal into a momentary HIGH pulse and wake the ESP up (just like when I was using a PIR sensor). So right now I have a 555 incorporated and wired up correctly. I know this because I’m able to light up an LED for a number of seconds when the SQW/INT asserts the alarm. So great - I must have a HIGH pulse - once again I thought all that’s left to do is connect the output pin of the 555 back to pin 12 of my ESP and set the code back to look for a HIGH pulse this time. (Note the LED is still connected for testing purposes).

But here’s where I need help: during the loop and still awake, the alarm is asserted, my ISR sees it, and the LED lights up for 2 seconds then turns off. Good! Then the time comes for the ESP to go into Light Sleep, I wait a minute for the next alarm to assert, and the LED lights up BUT it never turns off and the ESP never wakes up. It just stays asleep forever and the LED stays on forever. It's like pin 12 is constantly held HIGH. Or the output pin of the 555 is held HIGH. Or the SQW/INT pin is held LOW which keeps the input pin of the 555 LOW. Either way, the 555 isn't flipping back and resetting.

But why would it work as expected when the ESP is awake? And behave differently when it's asleep? Could it be that I'm not getting enough volts into my circuit? Would the ESP being in sleep somehow prevent the monostable circuit from charging its capacitor so that it never reaches 2/3 Vcc and never resets? That was never an issue when I was using a PIR.

Any thoughts or insights would be much appreciated! This one has me stumped for now. Thanks!!

Fritzing image attached and my code is below:

#include <Time.h>
#include <TimeLib.h>
#include <DS3232RTC.h>
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <Adafruit_NeoPixel.h>
#include <Event.h>
#include <Timer.h>
#include <Wire.h>


//external header files. 
extern "C" {
#include "gpio.h"
}
extern "C" {
#include "user_interface.h"
}


/*---------------------------Global Variables----------------------*/
//1. RTC variables:
//DS3231 clock;
volatile int countDown = (1000*20*1);
volatile int alarmFlag = false; 

void setup() {
  Serial.begin(115200);
  Serial.println("Running Setup Function");
  setSyncProvider(RTC.get);
  RTC.squareWave(SQWAVE_NONE);
  RTC.alarmInterrupt(ALARM_1, false);
  RTC.alarmInterrupt(ALARM_2, false);
  RTC.setAlarm(ALM1_MATCH_SECONDS, 20, 0, 0, dowWednesday);
  RTC.alarm(ALARM_1);
  RTC.alarmInterrupt(ALARM_1, true);
  pinMode(12, INPUT); // I won't need this pin but it is able to see the falling edge. 
  attachInterrupt(12, alarmISR, RISING); //this interrupt is working but I won't need it once I can wake up the ESP.
  delay(100);
}

void loop() {

  Serial.println("Running loop()");

  if (alarmFlag == true) {
    Serial.print("**********************the 20 second alarm just fired!*********************");
    RTC.alarm(ALARM_1);
    alarmFlag = false; 
  }
  
  if (countDown == 0) {
     delay(100);
     sleepNow();    
   } else {
     Serial.print("timer value is: ");
     Serial.println(countDown);
     countDown--;
   }

}

/* ------------------FUNCTIONS------------------------------------------------------*/

void sleepNow() {
  Serial.println("Going to sleep...");
  alarmFlag = false;
  RTC.alarm(ALARM_1);
  wifi_station_disconnect();
  wifi_set_opmode(NULL_MODE);
  wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); //light sleep mode
  gpio_pin_wakeup_enable(GPIO_ID_PIN(12), GPIO_PIN_INTR_HILEVEL);  
  wifi_fpm_open();
  delay(100);
  wifi_fpm_set_wakeup_cb(wakeupFromMotion); //wakeup callback
  wifi_fpm_do_sleep(0xFFFFFFF); 
  delay(100);
}

void wakeupFromMotion(void) {
  wifi_fpm_close;
  wifi_set_opmode(STATION_MODE);
  wifi_station_connect();
  countDown = (1000*20*1);
  Serial.println("Woke up from sleep");
}

void alarmISR()
{
  alarmFlag = true;
}

You can configure a 555 as a Schmitt trigger if that helps eg link

But may be also, you should be connecting GPIO16 to the Reset pin. See here.

6v6gt:
You can configure a 555 as a Schmitt trigger if that helps eg link

But may be also, you should be connecting GPIO16 to the Reset pin. See here.

Hi @6v6gt, thanks for the reply. I'm not familiar with the Schmitt triggers but I'll look into that as an option.

As for connecting GPIO16 to the Reset pin, I've actually reviewed that github thread a while ago. That's only necessary for those utilizing the Deep Sleep mode (which is different from Light Sleep) as the ESP can only be woken up from a hard reset. The reason I use Light Sleep is that the ESP can maintain its connection to its wifi AP and doesn't need to reset to wake up. It can just jump right back into it's loop without running the setup func all over again.