Counting tips
Lay the block along something that tips back and forth, a see-saw, a plank or a rocking toy, with its left and right edges toward the two ends, and count every time it goes over. The one thing counting adds to the first read is a filter: a new side counts only once SIGNAL has held it for 50 ms, longer than the balls rattle and shorter than a real tip.
Mount it across the tip
The switch feels only the tilt along the board's width. So the block goes on the plank with its left and right edges toward the plank's two ends, and each end of the plank's travel should take the can well past level: at 20 degrees or more the balls are firmly at one end or the other. A plank that only rocks a few degrees spends its time in the band where the balls stay wherever they last rolled.
How long to believe a change
Pick a filter. The trace is a plank tipping four times in 1.4 seconds, with the last two tips only a tenth of a second apart, and a rattle each time it lands. It is drawn to show the shape; the lengths are not measured. At 1 or 5 ms the sketch counts the rattle as tips. From 20 to 50 ms it counts four. At 100 ms and more it misses the quick pair: the plank was back before the filter believed it had gone.
The build uses 50 ms: the rattle is over well before that, and nothing a person can rock by hand tips back that fast.
How the sketch filters
raw is the last thing read, and rawSince is when it last changed. Every
bounce resets rawSince. steady changes only when raw has been
different from it for STABLE_MS, which a bounce never is. So one real tip
is one change of steady, and the count hangs off that.
There is no delay() in loop(). The filter is a comparison with
millis(), so the loop keeps reading thousands of times a second and
nothing is missed while it waits.
What you should see
At 115200 the serial monitor prints left end down or right end down for
the side it starts on. Tip it over: tip 1: right end down. Back: tip 2: left end down. Tap the plank or shake it gently at one end and nothing is
printed.
What it counts well
A see-saw, a rocking cradle, a tipping-bucket rain gauge, anything that spends its time clearly on one side or the other and crosses between them. It does not count vibration, and it does not measure angle. For a box that must notice being knocked over in any direction, use the four-direction tilt sensor's tip-over alarm.
The code
Reads SIGNAL on every pass of loop(), believes a change only once it has held for 50 ms, and then counts it and prints which end is down. No delay() anywhere, so nothing is missed while it waits.
/*
Tilt Sensor - counting tips TK62 / /p/tk62
Wiring, the same as the first read. Count from the square pad on
the TinkerBlock board, parts up, header at the bottom:
GND -> GND
VCC -> 3V3 on an ESP32, ESP32-S3 or Pico; 5V on an Uno
NC -> nothing (unconnected on the board)
SIGNAL -> GPIO 4 on an ESP32-S3, GPIO 25 on an ESP32,
D2 on an Uno, GP15 on a Raspberry Pi Pico
Mounting: lay the block along the thing that tips, a see-saw or a
plank, with the board's left and right edges toward its two ends.
Each tip from one end down to the other is one count.
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 pin SIGNAL is wired to.
// Uno: 2. ESP32: 25. ESP32-S3: 4. Pico: 15.
const int TILT_PIN = 4;
// A change counts once it has held this long: longer than the
// balls rattle, shorter than a real tip.
const unsigned long STABLE_MS = 50;
int raw; // the last reading
int steady; // the last reading that held
unsigned long rawSince; // when raw last changed
unsigned long tips = 0;
void setup() {
Serial.begin(115200);
pinMode(TILT_PIN, INPUT); // the board has its own pull-down
raw = digitalRead(TILT_PIN);
steady = raw;
rawSince = millis();
Serial.println(steady == HIGH ? "left end down" : "right end down");
}
void loop() {
int level = digitalRead(TILT_PIN);
if (level != raw) { // a rattle, or a real tip starting
raw = level;
rawSince = millis();
}
// Believe a change only once it has held for STABLE_MS.
if (raw != steady && millis() - rawSince >= STABLE_MS) {
steady = raw;
tips++;
Serial.print("tip ");
Serial.print(tips);
Serial.println(steady == HIGH ? ": left end down"
: ": right end down");
}
}One tip is one change of side, either way. With the block on a see-saw, a full rock down and back is two. The sketch compiles for an ESP32-S3 and an Uno.
View on GitHub · blocks/tk62-tilt-sensor/arduino/tilt_tip_counter/tilt_tip_counter.ino @ v1.5The same counter in MicroPython: remember when the reading last changed, and count a new side once it has held for STABLE_MS.
"""
Tilt Sensor - counting tips, MicroPython TK62 / /p/tk62
Wiring, the same as the first read. Count from the square pad on
the TinkerBlock board, parts up, header at the bottom:
GND -> GND
VCC -> 3V3
NC -> nothing (unconnected on the board)
SIGNAL -> GPIO 4 on an ESP32-S3, GPIO 25 on an ESP32,
GP15 on a Raspberry Pi Pico
Mounting: lay the block along the thing that tips, with the
board's left and right edges toward its two ends.
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.
"""
from machine import Pin
import time
# ESP32: 25. ESP32-S3: 4. Pico: 15.
TILT_PIN = 4
# A change counts once it has held this long: longer than the
# balls rattle, shorter than a real tip.
STABLE_MS = 50
tilt = Pin(TILT_PIN, Pin.IN) # the board has its own pull-down
raw = tilt.value()
steady = raw
raw_since = time.ticks_ms()
tips = 0
print("left end down" if steady else "right end down")
while True:
level = tilt.value()
if level != raw: # a rattle, or a real tip starting
raw = level
raw_since = time.ticks_ms()
# Believe a change only once it has held for STABLE_MS.
held = time.ticks_diff(time.ticks_ms(), raw_since)
if raw != steady and held >= STABLE_MS:
steady = raw
tips += 1
side = "left" if steady else "right"
print(f"tip {tips}: {side} end down")time.ticks_ms() wraps round, so the sketch measures with ticks_diff() rather than subtracting.
View on GitHub · blocks/tk62-tilt-sensor/micropython/tilt_tip_counter.py @ v1.5When it does not work
The sketch is counting the rattle. When the plank lands, the balls bounce off the contacts for a few milliseconds each, and a loop that counts every change sees each bounce. Keep STABLE_MS at 50, and do not add a delay() that makes the loop miss the settled level.
A tip that comes back before STABLE_MS has passed is never believed, and neither is its return. At 50 ms that only happens with something rocking ten times a second or faster. Lower STABLE_MS to 20 if your plank really is that quick, and watch for the rattle coming back.
Only a tilt that lowers the left or right edge moves the balls. Turn the block so that its left and right edges point at the two ends of the thing that tips.
Something is holding it near level: within about 10 degrees either way the balls go wherever a vibration sends them. Mount it so that each end of the tip takes the can well past level, 20 degrees or more, and the filter does the rest.
The LED, then the wires, then the angle: what to check, in order.
When it reads wrong →Edit this page — content/books/tilt-sensor/counting-tips.mdx
Questions about this product
See what other owners have asked, and read their solutions.
Tilt Sensor
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.