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
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 - 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.
The same in MicroPython. The mode is read once at the top of the script, before the loop, which is MicroPython's setup(). Save it as main.py so it runs at every power-up.
"""
Latching button - a mode chosen at start-up, MicroPython TK05
Wiring. Count from the square pad on the TinkerBlock board, switch
side up, header at the bottom:
GND -> GND
VCC -> 3V3 (never 5V: SIGNAL is VCC when the switch is on,
and these are 3.3 V pins)
NC -> nothing (unconnected on the board)
SIGNAL -> GPIO 25 on an ESP32, GPIO 4 on an ESP32-S3,
GP15 on a Raspberry Pi Pico
Thonny
Run > Configure interpreter MicroPython (ESP32) or
MicroPython (Raspberry Pi Pico)
Save it to the board as main.py to run it on every power-up.
Nothing to install: machine and time are built in.
"""
from machine import Pin
import time
# The GPIO number SIGNAL is wired to. ESP32: 25. ESP32-S3: 4. Pico: 15.
SWITCH_PIN = 4
switch = Pin(SWITCH_PIN, Pin.IN) # the board's pull-down holds it LOW
# The switch kept its position through the reset. Read it.
test_mode = switch.value() == 1
if test_mode:
print("Started in TEST mode (switch ON)")
else:
print("Started in NORMAL mode (switch OFF)")
warned = False
started = time.ticks_ms()
last_report = started
while True:
now = time.ticks_ms()
if test_mode and time.ticks_diff(now, last_report) >= 1000:
last_report = now
up = time.ticks_diff(now, started) // 1000
print("test: up for", up, "s")
# Moved while running? Say so once; it counts from the next reset.
if (switch.value() == 1) != test_mode and not warned:
print("Switch moved: press reset to change mode")
warned = TrueSaved as main.py, it runs at every power-up, so unplugging the board and plugging it back in is your reset. Ctrl-D at the prompt in Thonny's shell soft-resets the board, which also runs main.py again from the top.
When it does not work
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.
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.
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().
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.
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
Questions about this product
See what other owners have asked, and read their solutions.
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.