latching button/Reading it/07. Surviving a reset
Reading it · 07 of 9

Surviving a reset

A reset wipes every variable in your sketch, but it cannot move a switch. Read the TK05 in setup() and the sketch comes back in the state it was left in, after a reset, a crash or a power cut.

Who remembers

Surviving a reset
Step
1 of 5
TK05 sketch
ON
TK04 sketch
ON
Both are on. The TK05 is on because its switch is latched; the push-button sketch is on because a press set a variable in memory. Run it.

Both sides start on. The TK05 is on because its switch is latched. The push button is on because a press flipped a variable in the sketch's memory. Then the board is reset, and later unplugged.

A reset starts the sketch again from the top. Every variable is created afresh at the value it is declared with, so the push-button sketch comes back off, whatever it was before. The switch on the TK05 is a piece of plastic held by a latch. Nothing electrical moves it, so it is exactly where it was, and a sketch that reads it in setup() is back in the right state before loop() has run once.

Unplugging is the same story, harder. With no VCC the LED on the block goes out, but the switch stays latched. Plug in again and the first read finds it where you left it.

Read it in setup()

The sketch reads the pin once, in setup(), and decides its mode from that: TEST if the switch is on, NORMAL if it is off. In TEST it prints how long it has been running, every second. In NORMAL it says nothing.

Try it with the switch on: press the board's reset button, and the first line is Started in TEST mode. Press the switch, press reset again, and it starts in NORMAL. On an Uno, opening the serial monitor resets the board, so each time you open it you see the start-up decision again.

Chosen at start-up, on purpose

The sketch keeps reading the pin in loop(), but only to notice that it has moved. It then says so once and carries on in the mode it started in. That is a design choice, not a limitation: some decisions are safer made once, before anything starts, such as whether to wipe saved settings, which of two programs to run, or whether to wait for a set-up step. For a choice that should take effect at once, a level, not an event is the pattern to use.

What it cannot do

The sketch can read the switch and never set it. If the program decides by itself to be off while the switch says on, the switch is now lying to whoever looks at it, and there is no way to move it back from code. Use the TK05 for choices a person makes and leaves made. For an on and off the program also controls, a TK04 push button and a variable is the honest design.

The code

Reads the switch once, in setup(), and runs in one of two modes: TEST prints every second, NORMAL stays quiet. Press reset with the switch on and off to see it come back in the right one.

latching_button_mode_at_startup.ino
/*
  Latching button - a mode chosen at start-up           TK05 / /p/tk05

  Wiring. Count from the square pad on the TinkerBlock board, switch
  side up, header at the bottom:

    GND    -> GND
    VCC    -> 5V on an Uno; 3V3 on an ESP32, ESP32-S3 or Pico
              (never 5V on a 3.3 V board: SIGNAL is VCC when on)
    NC     -> nothing   (unconnected on the board)
    SIGNAL -> D2 on an Uno, GPIO 25 on an ESP32, GPIO 4 on an
              ESP32-S3, GP15 on a Raspberry Pi Pico

  Arduino IDE
    Tools > Board                 your board, e.g. ESP32S3 Dev Module
    Tools > Port                  the one that appears when you plug in
    Tools > USB CDC On Boot       Enabled   (ESP32-S3 only)
    No library needed.
*/

// The GPIO number SIGNAL is wired to.
// Uno: 2. ESP32: 25. ESP32-S3: 4. Pico: 15.
const int SWITCH_PIN = 4;

bool testMode;                    // decided once, in setup()
bool warned = false;              // said "Switch moved" yet?
unsigned long lastReport = 0;

void setup() {
  Serial.begin(115200);
  pinMode(SWITCH_PIN, INPUT);     // the board's pull-down holds it LOW

  // The switch kept its position through the reset. Read it.
  testMode = digitalRead(SWITCH_PIN) == HIGH;
  Serial.println(testMode ? "Started in TEST mode (switch ON)"
                          : "Started in NORMAL mode (switch OFF)");
}

void loop() {
  if (testMode && millis() - lastReport >= 1000) {
    lastReport = millis();
    Serial.print("test: up for ");
    Serial.print(millis() / 1000);
    Serial.println(" s");
  }

  // Moved while running? Say so once; it counts from the next reset.
  bool on = digitalRead(SWITCH_PIN) == HIGH;
  if (on != testMode && !warned) {
    Serial.println("Switch moved: press reset to change mode");
    warned = true;
  }
}

The mode is decided at start-up on purpose. If the switch is moved while the sketch runs, it says so once and carries on, and the new position takes effect at the next reset. The same pattern chooses a set-up mode, a logging level or a test routine.

When it does not work

I moved the switch and the mode did not change.

That is what this sketch is for: it decides the mode once, in setup(), and says Switch moved when the position no longer matches. Press the board's reset button and it starts again in the new mode. If you want the change to take effect at once, use the sketch from the previous article instead.

My Uno restarts every time I open the serial monitor.

That is the Uno, not the sketch. Opening the serial port resets an Uno so that it can be programmed without pressing a button. Here it is a free demonstration: every time you open the monitor, the sketch starts again and reads the switch afresh.

The LED went out when I unplugged the board. Did it forget?

No. The LED is powered from VCC, so it goes dark with no power. The switch is a mechanical latch and stays where it was. Plug the board back in and the LED lights again, and the sketch reads the same position in setup().

Can the sketch turn the switch off?

No. Nothing electrical moves the latch; only a press does. A latching switch that says ON while the sketch has decided to be OFF is a control that lies, so use it for choices the person makes, such as a mode, and not for a state the program may need to change by itself.

Where this goes next

Why the change sketch waits 20 ms before it believes the switch.

Bounce at each change

Edit this page — content/books/latching-button/surviving-a-reset.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

Latching Button

Loading discussions…

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Modules and blocks on the forum