Deep Reset Tutorial

This tutorial is a simple example of how to use the EN pin on the Argon/Boron/Xenon to power down the device for around 30 seconds.

Say you have a Boron in a remote location. The device knows it’s having trouble connecting to the cloud. Maybe power cycling it would help. This simple circuit powers off both the modem and the nRF52 MCU using an external timer. Pulling the EN line low turns off the load switch powering the modem and the nRF52 MCU on the Boron.

On the Argon and Xenon it powers off the XCL223 3.3V regulator, which will de-power the nRF52 MCU and on the Argon, the ESP32.

After about 30 seconds, the device will be allowed to boot normally.

Updates and the associated files can be found here:
https://github.com/rickkas7/DeepReset

Test Board

This is the test board for this circuit. While you can build this board exactly as is, you’ll typically want to include the circuit on your own board rather than dedicate an entire FeatherWing to resetting.

Schematics:

Board layout:

By default D2 is the deep sleep pin, but you can change that using the configuration jumper pads on the bottom of the board.

If you set D2 to OUTPUT and make it go HIGH, the device will immediately power down for around 30 seconds, then essentially cold boot. The MCU and modem will be de-powered during this time using the EN pin.

You can tell it’s working because the device turns off, the EN pin goes LOW, and 3V3 will become unpowered during this deep reset de-powered phase.

Eagle directory

The eagle directory in the Github repository contains:

  • DeepReset2.sch - schematic
  • DeepReset2.brd - board layout
  • DeepReset2v1.zip - Gerbers
  • DeepReset2.lbr - library containing all of the components in this design

BOM

Quantity Item Example
2 10K resistor 0603 Panasonic ERJ-PA3J103V
1 100K resistor 0603 Panasonic ERJ-3EKF1003V
1 2.7M resistor 0603 Panasonic ERJ-3GEYJ275V
1 0.01uF capacitor 0603 Murata GCM188R72A103KA37J
1 10uF capacitor 0805 Murata GRM21BR61C106KE15L
2 RS1JFP diode ON Semiconductor RS1JFP
2 2N7002 N-MOSFET ON Semiconductor 2N7002LT3G
1 TS555 Timer ST Microelectronics TS555
1 RT9818 Voltage Detector Richtek RT9818C-29GV
Male header pins 0.1" Sullins PRPC040SAAN-RC

Firmware

This is the test firmware. When you hit the MODE button, the device should immediately go into deep reset for 30 or so seconds.

#include "Particle.h"

SYSTEM_THREAD(ENABLED);

SerialLogHandler logHandler;

const int DEEP_RESET_PIN = D2;

void buttonHandler();

void setup() {
	pinResetFast(DEEP_RESET_PIN);
	pinMode(DEEP_RESET_PIN, OUTPUT);

	System.on(button_click, buttonHandler);
}

void loop() {

}

void buttonHandler() {
	Log.info("about to deep reset");

	digitalWrite(DEEP_RESET_PIN, HIGH);

	delay(1000);
	Log.info("this should never be reached");
}

The setup code look like this:

pinResetFast(DEEP_RESET_PIN);
pinMode(DEEP_RESET_PIN, OUTPUT);

Note the use of pinResetFast. This is necessary because digitalWrite does not work before the pin is set to output. Since the default state of outputs is LOW the pinResetFast shouldn’t be necessary, but I added it to be safe. This makes sure the pin won’t go briefly high, which will cause the device to go to deep reset immediately.

Configuration Pads

On the bottom side of the board are a number of trace jumpers that configure which pin is the deep reset pin. The default is D2.

To change it, cut the trace on the D2 pads, highlighted here:

Then close one of the other trace jumpers on D3, D4, A0, A1, or A2. A little blob of solder should do it. And, if you want to change it again, you can just vacuum or solder wick the blob off and move it to another pad.

Circuit Deep Dive

diodes

These two RS1JFP diodes allow the board to be powered either by USB or battery for flexibility. It you will only be powered by one or the other you can just skip the diodes, but if you could be powered with either than you’ll need the diodes.

drst-pin

One pin is used to enter deep reset by setting the pin as OUTPUT and setting it HIGH. This circuit is necessary for a few reasons:

  • The TS555 Timer requires an active low trigger.
  • The DRST line connects to the TS555 timer TRIGGER line with a pull-up to PWR, which can be up to 4.9V when powered by USB. Connecting GPIO directly to DRST would damage the GPIO.
  • The 2N7002 N-channel MOSFET prevents this higher voltage from flowing backwards into the GPIO pin and also inverts the signal.

The state of the timer at power-up cannot be guaranteed. To make sure that the device immediately starts when powered on, a Richtech RT9818 power detector is connected to the RESET pin on the TS555 timer. There’s a 100K weak pull-up on the pin as the RT9818 is an open-collector active-low output. The RT9818 is $0.41 in single quantities.

You can omit it, however sometimes the device will then go into deep reset at power-up. It will recover after 30 seconds, but it’s disconcerting when it happens so I like to include the RT9818.

monostable

This circuit is from the datasheet and describes using a 555 timer in monostable (one-shot) mode.

The control voltage capacitor is always 0.01µF. The configurable part is R and C.

timer

The actual circuit has:

  • R is 2.7 MΩ
  • C is 10µF

The timing formula for monostable operation is:

  • 1.1 × R × C

Where:

  • R is in ohms
  • C is in Farads

So:

  • 1.1 × 2.7E6 × 10E-6 = 29.7 seconds

This page has a great introduction to the various modes of the 555 timer.

By the way, this particular circuit uses the ST Microelectronics TS555. The classic bipolar 555 timer requires a minimum of 4.5V and 20 mA to do its thing. The TS555 works from 2V to 16V at around 100 µA, making it much better suited for battery-powered applications.

output

Finally, the output circuit uses a 2N7002 N-channel MOSFET. The timer output is active high, and the MOSFET pull the EN line low when the timer output goes high. The EN line has a 100K weak pull-up on it on the device itself, so this works perfectly.

Also, the TS555 timer can be running at 4.9V when powered by USB. We don’t want to drive the EN line with that high of a voltage, so using the N-channel MOSFET in open-collector style is preferable.

17 Likes

Very nice design and writeup, Rick. I’ve already incorporated something similar, but I’m sure many folks here will appreciate this design.

1 Like

Nice! Thanks for sharing.

1 Like

@rickkas7 I incorporated this dep reset into my PCB and now receiving some very unusual behavior I was hoping you could shed some light.

I incorporated this design into my PCB that I was having manufactured by PCBWay. However, I ended up using pin A5 instead of one of the digital output pins located in your design due to PCB layout and other uses I already had on the other pins. I assumed I could use any discrete output for this. My design also uses the Lora RFM95 radio (specifically the LoRa Featherwing by Adafruit: https://www.adafruit.com/product/3231.

//Define pins for the RFM9x:
#define RFM95_CS D6
#define RFM95_RST D3
#define RFM95_INT D2
#define RF95_FREQ 915.0

// Establish instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);

In the setup portion of the code I have this:

  pinResetFast(deepRst);
  pinMode(deepRst, OUTPUT);

//Define pim mode for RFM95 radio
  pinMode(RFM95_RST, OUTPUT);

  // Perform initial manual reset on RFM95 radio. 
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);

  rf95.init();

… (the reset of the code)

However, as soon as the rf95.init() is called, it will trip the deep reset circuit and I can’t figure out why. If I comment out the rf95.init() line, it will function as it should and NOT do a deep reset so something within that function is causing pin A5 to go high or enough of a signal on A5 to trip the Deep Reset Circuit.

I confirmed the pin definition for A5 is deepRst and I cannot find a definition for A5 anywhere else including the <RH_RF95.h> library. Looking in the CPP of the library, rf95.init() is used primarily to set the interrupt pin. Am I missing something obvious, I’m been starring at this for hours… a little guidance is greatly appreciated! What am I missing here? I’ve tried this with the Particle Argon as well as a Particle Boron LTE with the same behavior. If I take a knife and cut the trace from pin A5 then I don’t have any issue (except I also don’t have a deep reset functionality :frowning: ). On the plus side, the deep reset for 30 second behavior seems to work perfectly, just not when I want it to. Your thoughts or guidance would be greatly appreciated!

Which library are you using?
The RH_RF95 library in the public Particle library repository doesn’t seem to be doing anything useful an doesn’t even sport an RH_RF95::init() method.

BTW, when only calling SPI.begin() without a dedicated CS pin A5 will be assumed as the default SS pin (including some default setup procedure) as mentioned here
https://docs.particle.io/reference/device-os/firmware/boron/#spi

If you were using a derivative library from Paul Stoffregen’s RH_RF95 library then this might be your issue.

Hence it would be important to see the library implementation to tell how it’s working internally.

When dealing with unexpected GPIO behaviour it’s also helpful to acquire trace of the signal in question (e.g. via logic analyser or oscilloscope) to get a feeling what the issue could be.

@ScruffR, Thanks for the reply, the actual library I used was RF9X-RK: https://github.com/rickkas7/RF9X-RK

I started with this example: https://github.com/rickkas7/RF9X-RK/blob/master/examples/1-encrypted-server/rf95_encrypted_server.cpp. This example had the #include <RH_RF95.h> and then uses if (!rf95.init()) line. So in VS Code my library/src folder look like this:

Since I have the import RH_RF95.H, it’s a modified/local version of that library that is imported and used as I understand it. It’s the rf95.init() line of code that trips the Deep Reset. If I comment that out then it doesn’t.

I’ll dig into the libraries more as well, I have a feeling the A5 pin is assumed the default somewhere and is being used somewhere within that library as you mentioned. That said, my initial understanding is when I create the instance of rf95, it should be taking my CS pin and INIT pin as reference. Maybe my library or how I am trying to use that library isn’t quite right. I’m not strong in the firmware/library management but willing to dig in to see what I can learn. I may start with a clean slate to help me troubleshoot some and try and narrow it down. I also have a debugger I can try and pull out to find the exact line of code it trips at.

// Establish instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);

Yes, I agree having an oscilloscope would certainly help. With Covid, I lost access to the Oscilloscope I was using. I am tempted to order a new one for my personal use at home but would rather not unless I had to.

Any insight or guidance would be appreciated!

1 Like

I released version 0.0.4 of the RF9X_RK library to fix this problem. The RHHardwareSPI.cpp file calls SPI.begin() with no parameters, which initializes the SPI peripheral to use the default SPI SS pin, which is A5. Now it passes PIN_INVALID so it does not initialize the pin. RHSPIDriver initializes the CS pin that is passed to the constructor separately.

0.0.4 (2020-09-09)

  • Modified the hardware SPI initialization to not set the default SS pin (typically A5) as an output and high, regardless of what was configured as the CS pin.
3 Likes

@rickkas7 - You rock! I just installed the new library, compiled downloaded and issue fixed! Thank you, thank you, thank you!

@ScruffR - Thanks for putting me in the right direction regarding A5 as default SS for SPI. I still have lots to learn but this is all part of the fun. :slight_smile:

Thank you both very much!

2 Likes

Hi all. I know the topic is not new, but wanted to add for the benefit of all that the A5 has the same behaviour as you describe regardless of whether you’re using such library. It does not initialize in 0 and has a very brief peak to HIGH when the ARGON is powered up before getting to LOW. Even with the pinResetFast(deepRst) line early in the code.

We have a similar approach to a deep-reset circuit which was supposed to be triggered by a HIGH signal in A5 pin. We tested the board with a very simple sketch (no libraries at all). Just set the A5 pin in HIGH through a particle.function which would triggered the deep-reset circuit. Since the A5 goes to HIGH inmediately after powering-up the ARGON, then chip itself starts a cicle of endless deep-reseting as the pin goes high when powered up, resets the argon, then power up, goes high, and so on.

1 Like