Question about NE555 Timer as a "One Shot" IC

Hi Everyone,

I'm hoping folks with more hardware experience can help me sort through an issue I'm having and not understanding. What I'm trying to do with a current project is run some code on an ESP8266, put it to sleep, and wake it up using a real time clock (RTC) that has alarm functions. When the RTC alarm is asserted, its SQW/INT pin goes low, however, since I can't programmatically clear the alarm (by resetting the alarm flag) once the ESP is asleep, the SQW/INT pin simply stays low. Which means, even though my ESP should wake up on a low pulse, there is no "pulse" because the pin is constantly low.

So at the recommendation of other users, I've incorporated a 555 timer in mononstable mode and in series with the SQW/INT pin to achieve a high pulse. I have it all wired up correctly (I've verified with an LED while the ESP is awake) to function as a "one shot" IC. In theory, as soon as the trigger pin goes low, it should issue a timed high pulse. However, that's not the case. Similar to before, the trigger pin is being held low and the output pin is thus held high. There is no "pulse."

And here is my question. If the trigger pin is constantly held low, will the capacitor ever discharge and reset the timer? It seems like my issue is either: 1) the trigger pin held low prevents the capacitor from discharging, keeping the output pin high; or 2) the trigger pin held low prevents the voltage across the capacitor from reaching 2/3 of VCC, keeping the output pin high.

Either way, I'm not getting the timed "pulse" the timer is supposed to generate, just a constant signal. Am I not understanding the limitations of the timer? Am I missing a needed component? How can I achieve a timed pulse if this one pin is being held low?

Any insight would be really helpful!

I would be helpful to know which RTC you are using.

It would be even more helpful if you stopped repeating yourself.

srnet:
I would be helpful to know which RTC you are using.

Sorry about that, I wasn't sure if that info was useful. I'm using the DS3231 real time clock. I'm also using this library to help set and adjust the alarms: GitHub - JChristensen/DS3232RTC: Arduino Library for Maxim Integrated DS3232 and DS3231 Real-Time Clocks

I guess you can use a decoupling cap between trigger of 555 and alarm of RTC. But it seems strange something like that is needed... At worst case you can use decoupling cap directly between RTC and ESP to get pulse (level is not enough?).

AWOL:
It would be even more helpful if you stopped repeating yourself.

My browser hung after I hit post and after I refreshed I didn't see it anywhere in the Project Guidance section so I re-posted. My apologies if I duplicated the original post by accident.

I have the micro wake up on /INT going low, reset the RTC alarm, do whatever else it needs to do, and go back to sleep.

No need for any additional circuitry, except to make sure there is a pullup resistor on the /INT pin of the DS3231, as it is open collector.

jremington:
I have the micro wake up on /INT going low, reset the RTC alarm, do whatever else it needs to do, and go back to sleep.

Me too.

Cant work out why a 55 timer is needed.

I have the micro wake up on /INT going low, reset the RTC alarm, do whatever else it needs to do, and go back to sleep.

No need for any additional circuitry, except to make sure there is a pullup resistor on the /INT pin of the DS3231, as it is open collector.

@jremington and @smet thanks for your replies. I appreciate it. So that approach was what I did first actually. I had a 10K pullup resistor on the SQW/INT pin and had it connected directly to pin 12 on my ESP and set the wakeupcallback to look for a LOW signal. However, that just didn't work. I believe it's because
until the alarm is cleared, the SQW/INT pin continues to output a LOW signal, so it just keeps the pin in my ESP low as well.

For instance, if I manually take the end of the jumper cable thats connected to the ESP and momentarily bring it to ground, the ESP wakes up and everything works as I expect it to. That's how I came to the conclusion that the pin needs to eventually return to near ~VCC in order for it to register the logic level change. I reached out to some folks on the forums with this issue and some suggested I use a 555 to generate a timed pulse. And that brings me to where I am now. But it still seems I'm stuck with a perpetual low signal which my ESP doesn't recognize. There might be a simple hardware solution that I'm just not aware of?

I am not that familiar with the ESP, but it sounds like the interrupt is set to trigger on a rising edge, it needs to be set to trigger on falling edge or low.

This ESP8266 tutorial explains how to have an interrupt on falling edge.

jremington:
This ESP8266 tutorial explains how to have an interrupt on falling edge.

Thanks, guys. I've also tried that as well. If only it was that simple. Unfortunately once the ESP is in sleep mode, it only recognizes logic level changes, not rising nor falling edges, as described in the Espressif documentation and this open issue.

That's why I've been focused on a hardware solution. It seems to be the only way.

I still don't understand the problem. According to your first link, in sleep mode the ESP8266 can be set to wake on LOW on any IO. That should certainly work with /INT, with a pullup to the ESP8266 Vdd.

Quote from the poorly written material in the first link:

b).void gpio_pin_wakeup_enable(uint32 i, GPIO_INT_TYPE intr_state) : (parm i is the gpio number) To enable the wake-up-by-gpio function.In this situation, interrupt mode can just be set to GPIO_PIN_INTR_LOLEVEL, GPIO_PIN_INTR_HILEVEL.That means for gpio,only level interrupt can wake up the chip

So:

  1. Wake up on low
  2. Clear the alarm
  3. Do stuff
  4. Go back to sleep

If you really, really, really need a hardware solution and are concerned about power, the 555 is not the way to go. Use a CMOS chip (e.g. CD4011) to make a one-shot, for negligible power consumption.

jremington:
I still don't understand the problem. According to your first link, in sleep mode the ESP8266 can be set to wake on LOW on any IO. That should certainly work with /INT, with a pullup to the ESP8266 Vdd.

@jremington Yes I totally agree with you. According to the documentation and how I have it wired up, the ESP826 should get woken up on LOW on any IO. The problem is that it doesn't. And my best guess right now is that it has something to do with the ESP pin being held LOW (opposed to going LOW then returning to VCC), thus not registering a state change and that's why I've been pursuing all these workarounds.

So I guess let me ask you this, have you dealt with that kind of issue before? Or am I not going about this the right way?

I haven't used the ESP8266, but I have worked with at least ten different kinds of microprocessors, as well as a wide range of much larger computers. I am very familiar with interrupt processing, sleep states, etc.

I can't imagine why your setup is not working, but then you haven't posted code or a clear wiring diagram, as expected for this forum, so it is unlikely that anyone would know what the real problem is.

Have you connected the grounds? Is the pullup on /INT to Vdd of the ESP8266?

My suggestion is to make sure you understand how interrupts work with sleep modes on the ESP8266. You don't need the RTC for that, just a breadboard, the ESP, a resistor to Vdd and a switch to ground, connected to some I/O pin.

My apologies for not posting those. I did include my code and a wiring diagram in another post that wasn't getting any traction so I thought I would just try to get some advice on hardware.

My code is below and a fritzing diagram is attached.

#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); //20 second count down. 
volatile int alarmFlag = false; 

void setup() {
  Serial.begin(115200);
  Serial.println("Running Setup Function");
  setSyncProvider(RTC.get);
  RTC.squareWave(SQWAVE_NONE); //disable the square wave output so I can utilize the interrupt output. 
  RTC.alarmInterrupt(ALARM_1, false);
  RTC.alarmInterrupt(ALARM_2, false); //start with both interrupts disabled, per the library documentation.
  RTC.setAlarm(ALM1_MATCH_SECONDS, 20, 0, 0, dowFriday); //set an alarm to fire once every minute, when seconds match "0:20"
  RTC.alarm(ALARM_1); //initate alarm. 
  RTC.alarmInterrupt(ALARM_1, true);  //enable an interupt to fire when the alarm is asserted.
  pinMode(12, INPUT); 
  attachInterrupt(12, alarmISR, FALLING); //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); //clear alarm flag. 
    alarmFlag = false;  //reset the ISR flag. 
  }
  
  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_LOLEVEL); //Look for low pulse on pin 12.
  wifi_fpm_open();
  delay(100);
  wifi_fpm_set_wakeup_cb(wakeupFromAlarm); //wakeup callback
  wifi_fpm_do_sleep(0xFFFFFFF); //go to sleep indefinitely.
  delay(100);
}

void wakeupFromAlarm(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;
}

jremington:
My suggestion is to make sure you understand how interrupts work with sleep modes on the ESP8266. You don't need the RTC for that, just a breadboard, the ESP, a resistor to Vdd and a switch to ground, connected to some I/O pin.

++++ In principle I agree, DIY testing.

In this case however, if the issue is related to edge detection of the interrupt a physical switch may not be a helpful simulation as contact bounce will often produce multiple pulses.

jremington:
My suggestion is to make sure you understand how interrupts work with sleep modes on the ESP8266. You don't need the RTC for that, just a breadboard, the ESP, a resistor to Vdd and a switch to ground, connected to some I/O pin.

First off let me just say thanks to you and @srnet for your engagement.

I know I don't need an RTC to issue an interrupt but I'm building the second iteration of a battery powered IoT project that doesn't have any kind of hardware interface. The user will manage the device over WiFi to set a time window for when the device is awake and all other times, the device is asleep. Since documentation seems to indicate the ESP needs an interrupt generated from an external source once its asleep, I've chosen to go with an RTC to manage the time and issue the interrupt.

srnet:
++++ In principle I agree, DIY testing.

In this case however, if the issue is related to edge detection of the interrupt a physical switch may not be a helpful simulation as contact bounce will often produce multiple pulses.

I'll keep testing.

the issue is related to edge detection of the interrupt

Contact bounce does not seem to an issue, because the ESP8266 evidently can't detect edges in sleep mode, only levels. To avoid multiple interrupts due to contact bounce, just wait 10 ms before going back to sleep.

According to the docs you linked, the following will not work in sleep mode. Try low level instead.

  attachInterrupt(12, alarmISR, FALLING); //this interrupt is working but I won't need it once I can wake up the ESP.

I wanted to follow-up and let folks know that I finally solved this issue. It was a hardware issue along, the very one that I thought might be preventing my ESP from recognizing a logic level shift. I found a response to this old post on stackexchange which makes mention of a potential issue when using the 555 in monostable mode if the TRIGGER pin is held low.

Looking at the interior circuit of the 555, if the TRIGGER input is held low for longer than pulse length, it will keep the lower comparator CBB high and the OUTPUT will remain high.

The poster shared a schematic that would help get around this issue, which I was able to add into my circuit. With just four components, my ESP now wakes up when the RTC asserts its alarm. After studying the schematic closer and digging into what's actually happening on each of the pins, I determined that the behavior of the 555's TRIGGER pin and any I/O pin of my ESP should be identical (since the ESP can be woken up from any I/O pin when it goes from high to low and back again). Meaning, I shouldn't need the 555 now that I have these extra components at work.

So I'm happy to report that I was able to eliminate the 555 and now just have the SQW/INT pin of my RTC connected directly to the ESP with the help of this additional sub-circuit. A copy of the schematic is attached for those curious and incase it helps others with their projects.

Thanks to everyone for their time and attention.