Category: Home Control

Erratum – Arduino external forced reset circuit

My previous post (Watchdog watchdog) sought to fix a problem – the Arduino ATmega328 I was using to monitor my heating system would occasionally hang. It would remain hung despite the use of the built-in watchdog timer to reset it. I’m not sure why, but I suspect it’s related to the electrical environment. In particular, I’ve replaced the entire Arduino board, and tested the program on the bench (where it worked perfectly, resetting as intended). I tried reconfiguring the watchdog interrupt service routine to pull Arduino pin 12 low and connected that to the ~RESET line. Still no good.

Fast forward (a few years!) while I ignore the problem and manually reset the Arduino every couple days. Finally, I designed and built a new circuit to power-cycle the Arduino; it worked perfectly on the bench. But not in deployment. Rats!

So I did a little modification – I removed the MOSFET and other power-cycling components, and dedicated a pin of the ATtiny to the inverse of the power-cycling pin – it is pulled low when a reset was needed. That pin is connected to the ~RESET line on the Arduino board. It looks like this works. I’ll update this post with news, and if it looks good, with the new program and circuit documentation.

Watchdog watchdog

Well. It’s been a while. Here’s what’s new:

I monitor my heating system (temperatures, zone activation) with an Arduino, and relay the values to my home monitoring system through an ESP-01 / ESP8266. The Arduino occasionally hangs up.

I have tried to fix this by checking the power supply for good clean power; by making it reboot itself every 24 hours; by enabling the ATmega328’s watchdog timer. It still hangs up.

When it is running, it flashes an LED connected to the standard pin 13 of the Arduino. I recalled seeing that a 555 timer could be used as a missing-pulse detector. This would trigger if the 1Hz flashing stops. Cool. The missing pulse detector takes its output low during pulse starvation, and takes it high during the happy times when the pulses continue. I needed to take that prolonged low value and turn it into a one-shot pulse to drop and resume the power to the Arduino, and a second 555 could be configured as a one-shot to create this pulse. I had to add a capacitor in between to prevent continuous retriggering of the second 555, which would keep the power off to the Arduino.

The circuit “1” in the schematic illustrates this setup.

I happened to have a 556 handy, which comprises the functionality of two 555 timers. The equivalent simpler circuit is “2” in the schematic.

But, duh. I’m really more of a programmer at heart. And I had some ATtiny85 chips around. So I created an Arduino program to embody all the above functionality in a much simpler circuit – “3” in the schematic.

Note: in the code and the schematic the name ATmega refers to the (processor on the) Arduino board.

Watchdog_watchdog_sch

And I put it all onto a very small solderless breadboard. Since I needed regulated 5V to feed all the components, I put standard voltage regulation onto the breadboard as well.

The Arduino program was very simple:


/*
  Watchdog_watchdog
  
  One of my Arduinos, the one that monitors temperatures and zone activations 
  in my heating system, occasionally hangs up. This despite the fact that I'm
  using the ATmega watchdog to automatically reset it if it hangs. Dunno why. 
  The power seems good and stable. I've tried replacing the ATmega chip.

  I've decided to kill a flea with a cannon. The ATmega blinks an LED at 1Hz
  to indicate that it's still alive - I call this a throbber. The ATtiny will 
  monitor the throbber and if it stops, it will power-cycle the ATmega.
  Hah.

  The MOSFET in question will be a p-channel MOSFET configured on the high side
  of the power to the ATmega; when its gate is pulled low, it allows power to 
  flow to the ATmega. The specific MOSFET I'm using is a 5LP01SP, which is a 
  p-channel device whose pins are 1=source, 2=drain, 3=gate.
  
*/

#define pdThrobber_in 3
#define pdMOSFET      4

const unsigned long resetAfter_ms = 2000UL;
unsigned long lastThrobAt_ms = 0UL;


void setup() {
  pinMode ( pdThrobber_in, INPUT );
  pinMode ( pdMOSFET, OUTPUT );
}

void loop() {
  static int throbberStatePrevious = 0;
  int throbberState = digitalRead ( pdThrobber_in );
  if ( throbberState != throbberStatePrevious ) {
    lastThrobAt_ms = millis();
    throbberStatePrevious = throbberState;
  }
  if ( ( millis() - lastThrobAt_ms ) > resetAfter_ms ) {
    // BOOM. Cause a reset
    digitalWrite ( pdMOSFET, 1 );  // turns off ATmega
    delay ( 500 );
    digitalWrite ( pdMOSFET, 0 );
    delay ( 5000 );  // time enough to let the ATmega boot up
    lastThrobAt_ms = millis();  // reset the watchdog
  }
}

Updating some, but not all, old technology

Lightning strikes. It struck near me, and fried a component of my old X10 home-control system.

X10 is a power-line-based communications network. Data is sent (slowly) over the house power lines by injecting a 120 kHz signal into the 60 Hz AC signal just after the zero-crossing of that signal. One bit per cycle is sent by either adding or withholding a short pulse of the 120 kHz.

[Read More...]