Learning Goals 5 min
By the end of this lesson you will be able to:
- Describe what's physically inside a tilt switch — a tiny metal can, a ball bearing, and two contacts — and explain why tipping it one way closes the circuit while tipping it the other way opens it.
- Wire a tilt switch exactly like the L01-17 button (two leads, no polarity,
INPUT_PULLUP) and read its state withdigitalRead— getting HIGH or LOW depending on orientation. - Use the reading to drive an LED, beep a buzzer, or trigger an alarm, and apply the L01-18 debouncing trick to ignore the brief "chatter" as the ball settles.
Warm-Up 10 min
L01-38 was heavy maths. Today is a holiday. The tilt switch is the simplest motion sensor on earth — it's a button that gravity presses for you — and wires up exactly like a button you already know how to use.
Quick-fire puzzle
Tip your phone or laptop screen-side down on the table. Notice what happens — the screen probably rotates, the speakers might mute, perhaps an automatic feature kicks in. The device is sensing its orientation, not just its motion.
- If a device "knows when it's tipped upside down", what's the simplest two-state question it's asking — and what's the simplest sensor that could answer it?
- What would a pre-2007 flip phone have used to detect "the lid is open"? Could the same kind of thing detect "the phone is upside down"?
- How precise is "upside down" really? Is 89° just-not-flat the same as 95° just-tipped-over, or different?
Reveal the answer
- The simplest question is "tilted or not?" — a yes/no answer. The simplest sensor is a switch that opens or closes based on which way is down. Modern phones use accelerometers (Level 2) that report fine orientation in 3D, but you don't need 3D to know "am I upside down".
- A tiny mechanical switch — usually a magnet-and-reed or a spring contact — that closed when the hinge was open. Today's tilt switch is the same idea: a mechanical switch whose actuation comes from gravity instead of a hinge.
- A tilt switch has a small "dead zone" of a few degrees where it's neither solidly tilted nor solidly upright. Inside that dead zone the ball bounces between contacts and the reading flickers — exactly like a button's contact bounce in L01-18. The L01-18 debounce trick works here too.
New Concept — a button that gravity presses 15 min
The big idea — what's inside the can
A tilt switch (also called a ball switch or SW-520D by its most common part number) looks like a small silver cylinder about the size of a grain of rice with two leads sticking out of one end. Open one up (don't, they're sealed) and you'd find:
- A small ball bearing made of conductive metal.
- Two spring contacts at the open end of the can, each connected to one of the external leads.
- The ball rolls freely inside the can.
When the can is tipped so the open end is down, gravity rolls the ball onto the two contacts, bridging them — the switch is closed (continuous). Tip it the other way and the ball rolls to the closed end of the can; the contacts have nothing bridging them — the switch is open. That's it. A switch you flick by tilting.
Wiring — exactly like a button
Electrically, a tilt switch is just a switch. No polarity. No semiconductor. Wire it like the button from L01-17:
- One lead → an Arduino digital pin (say D7).
- Other lead → GND.
- In
setup():pinMode(7, INPUT_PULLUP).
The pull-up resistor inside the chip holds the pin at HIGH when the switch is open (ball away from contacts). When the switch closes (tilted), the pin is pulled to GND through the switch — reads LOW. Same logic as a button: HIGH = not actuated, LOW = actuated.
Reading the state
int tilt = digitalRead(7); // HIGH = upright, LOW = tipped
if (tilt == LOW) {
// device is tilted right now
}That's the whole interface. Whether "tilted" means upside-down, sideways, or some specific angle depends entirely on how you mounted the switch. The chip sees only "switch open" or "switch closed".
Ball bounce — debouncing returns
Just like a button, the ball bearing doesn't snap cleanly onto the contacts. It rolls, bounces a few times, and finally settles. During those few milliseconds the switch reads HIGH-LOW-HIGH-LOW-LOW rapidly — exactly the contact bounce from L01-18. The fixes are the same:
- Cheap fix: add
delay(20)after a state-change to wait out the bounce. - Better fix: only act on the moment the state changes (L01-19 state-change detection) and require the new state to hold for at least 50 ms before believing it.
For most tilt-driven sketches, the cheap fix is good enough — orientation events are slow compared to button-press events.
What it's good for — and what it isn't
A tilt switch is excellent at:
- Tip-over detection (a desk lamp that turns off when knocked over).
- "Was it moved?" alarms (a package that beeps if picked up at the wrong end).
- Crude orientation sensing ("is it upright or upside down?").
- Shake detection (rapid alternation between open and closed = the user is shaking it).
It is not good at:
- Telling you the exact angle of tilt (it's binary — tilted or not).
- Distinguishing "slowly leaning over" from "suddenly knocked over" (both produce the same single transition).
- Detecting motion without a change in orientation (a smooth slide doesn't tip the ball).
For any of those, you'd reach for an accelerometer — a Level 2 sensor that reports X, Y and Z gravity components as continuous values. The tilt switch is the 50-cent ancestor of those parts; it does one thing, cheaply.
Why it matters
Tilt switches are everywhere in cheap consumer goods: cycling helmets that beep when you fall, lights that switch on when you pick up a torch, kids' toys that giggle when they're held the right way up, the "anti-theft" feature in old hotel TVs. Knowing this part also gives you a clean intuition for what comes next in Level 2 — the accelerometer, which is essentially "a tilt switch with measurements".
Worked Example — tip detector with an LED 20 min
You're going to wire the tilt switch and an indicator LED on the breadboard, write a sketch that prints the state live, and watch the LED change as you tip the switch by hand.
Step 1 — Wire it like a button + LED
Almost identical to the L01-17 button circuit, with an extra LED on D8:
- Tilt switch straddling two columns; one lead's column goes to D7 via a yellow signal wire, the other lead's column jumpers to the − rail.
- LED on D8 with a 220 Ω resistor, cathode to the − rail (L01-07 wiring).
- One GND wire from the − rail back to the Arduino's GND.
Step 2 — The sketch
// Tilt detector — LED lights when the breadboard is tipped sideways
const int TILT_PIN = 7;
const int LED_PIN = 8;
void setup() {
Serial.begin(9600);
pinMode(TILT_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
int tilt = digitalRead(TILT_PIN);
digitalWrite(LED_PIN, tilt == LOW);
Serial.println(tilt == LOW ? "TILTED" : "upright");
delay(100);
}Step 3 — Upload and tip
- Upload at 9600 baud, open the Monitor.
- With the breadboard sitting flat on the desk and the tilt switch's leads pointing up, the Monitor should print
uprightand the LED should be off. - Tip the breadboard sideways. Within 100 ms or so, the Monitor switches to
TILTEDand the LED lights up. - Tip slowly through the dead zone. You'll see the Monitor flicker briefly between the two states as the ball settles — that's the bounce.
- Hold the breadboard exactly at the critical angle. The reading might oscillate for several seconds — gravity is making the ball indecisive.
Step 4 — Add a quick debounce
The flicker through the dead zone is annoying for any logic that "acts once" on a tilt event. Add the L01-19 state-change detection with a 50 ms wait-out:
int lastTilt = HIGH;
void loop() {
int tilt = digitalRead(TILT_PIN);
if (tilt != lastTilt) { // state changed
delay(50); // wait the bounce out
int confirmed = digitalRead(TILT_PIN);
if (confirmed == tilt) { // still changed? real event
lastTilt = confirmed;
digitalWrite(LED_PIN, confirmed == LOW);
Serial.println(confirmed == LOW ? "TILTED" : "upright");
}
}
}Now the Monitor only prints once per real tilt event, regardless of how long the ball spent bouncing through the dead zone. This is exactly the L01-18 button debounce pattern, recycled.
Trace one tilt on paper
Fill in what the debounced sketch above does at each moment, assuming you slowly tip the breadboard sideways at t = 0:
| Time | tilt read | Branch taken | LED state |
|---|---|---|---|
| t = 0 (just tipped) | LOW | state changed → wait 50 ms | off (about to update) |
| t = 50 ms (re-read) | ____ | ____ | ____ |
| t = 100 ms (next pass) | ____ | ____ (no change since last) | ____ |
| t = 5 s (you tip it back) | ____ | ____ | ____ |
Walk through the table without uploading. The pattern is "ignore until something changes; then verify the change is real; then act once". Same shape as every event-driven input handler you'll ever write.
Try It Yourself — three tilt sketches 20 min
Goal: A tilt-alarm beeper. Add a piezo on D9 to the worked-example wiring. When the breadboard is tilted, the buzzer beeps continuously at 880 Hz; when upright, silence. The LED keeps mirroring the state as before.
const int TILT_PIN = 7;
const int LED_PIN = 8;
const int BUZZER_PIN = 9;
void setup() {
pinMode(TILT_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
if (digitalRead(TILT_PIN) == LOW) {
digitalWrite(LED_PIN, HIGH);
tone(BUZZER_PIN, 880); // no duration → keeps going
}
else {
digitalWrite(LED_PIN, LOW);
noTone(BUZZER_PIN); // silence
}
}Questions:
- This sketch uses no debounce. Does the buzzer stutter when you tip slowly through the dead zone? ____
- Why does
tone(BUZZER_PIN, 880)with no duration keep the note going forever, even thoughloop()calls it on every pass? ____ (Hint: see L01-14.) - Replace
880with200. Why does the alarm sound less urgent? ____ (Hint: human perception of pitch and danger.)
Goal: A tip-counter. Every time the breadboard tips over (upright → tilted transition only — not back), increment a counter and print the total to the Serial Monitor. Going back upright should print nothing.
Plan: use L01-19 state-change detection. Track lastTilt. On a HIGH → LOW transition, count it. Debounce with the worked-example pattern so each physical tip counts once.
const int TILT_PIN = 7;
int tipCount = 0;
int lastTilt = HIGH;
void setup() {
Serial.begin(9600);
pinMode(TILT_PIN, INPUT_PULLUP);
Serial.println("Ready — tip the breadboard.");
}
void loop() {
int tilt = digitalRead(TILT_PIN);
if (tilt != lastTilt) {
delay(50);
int confirmed = digitalRead(TILT_PIN);
if (confirmed == tilt) {
if (lastTilt == HIGH && confirmed == LOW) {
tipCount = tipCount + 1;
Serial.print("Tip count: ");
Serial.println(tipCount);
}
lastTilt = confirmed;
}
}
}Questions:
- Why does the counter only print on the HIGH → LOW transition, not the other way? Trace through what happens when you tip back upright. ____
- Without the 50 ms debounce, what would you see in the Monitor as you tipped slowly through the critical angle? ____
- The counter resets to 0 every time you reset the Arduino. How would you make it persistent across resets? ____ (Hint: that would need flash memory writes — Level 2 topic.)
Goal: A two-axis tilt rig. Wire two tilt switches on different pins, mounted at 90° to each other on the breadboard. Now you can detect tilting in either direction independently and report it as N/S/E/W on the Monitor.
Plan: tilt switch A on D7 (oriented to fire when tipped forward), tilt switch B on D8 (oriented to fire when tipped sideways). Each loop() pass reads both. Four possible states:
- A upright, B upright → "level"
- A tilted, B upright → "forward"
- A upright, B tilted → "sideways"
- A tilted AND B tilted → "diagonal"
const int TILT_A = 7;
const int TILT_B = 8;
void setup() {
Serial.begin(9600);
pinMode(TILT_A, INPUT_PULLUP);
pinMode(TILT_B, INPUT_PULLUP);
}
void loop() {
bool a = (digitalRead(TILT_A) == LOW);
bool b = (digitalRead(TILT_B) == LOW);
if (!a && !b) Serial.println("level");
else if (a && !b) Serial.println("forward");
else if (!a && b) Serial.println("sideways");
else Serial.println("diagonal");
delay(200);
}Questions:
- How does this compare to a real accelerometer? What can the accelerometer do that two tilt switches can't? ____
- If you wanted to detect "leaning at 45°" specifically, would adding more tilt switches help, or would you need a different kind of sensor? ____
- The L01-21 "combining two buttons" lesson did almost exactly this logic with two buttons. Could you reuse that sketch verbatim with two tilt switches? Why or why not? ____
Mini-Challenge — shake-to-trigger 10 min
"Detect a deliberate shake — not a single bump"
A single tip is one tilt event. A shake is many tilt events in rapid succession — the user rocking the breadboard back and forth. Today's challenge: detect a "real shake" defined as at least 4 transitions in any 1-second window, then flash the LED and beep when it fires.
Your task:
- Use the worked-example wiring (tilt on D7, LED on D8) plus the L01-39 easy task's buzzer on D9.
- Count tilt-state transitions (both HIGH→LOW and LOW→HIGH count) inside a rolling 1-second window using
millis()(L01-22 pattern). - When the count reaches 4 within the window, fire a "shake detected!" alarm — flash the LED three times and beep 200 ms at 1500 Hz. After firing, reset the counter so the same shake doesn't double-fire.
- The simplest "rolling window" implementation: every time you see a transition, save its timestamp to a small array of the last 4. The shake fires when
millis() - oldest_saved_timestamp <= 1000.
It works if:
- A single bump (one transition) does not trigger the alarm.
- A slow tip-up, tip-down sequence (two transitions over several seconds) does not trigger.
- Vigorous shaking for one second fires the alarm exactly once, then waits to be shaken again.
Reveal one valid sketch
// Shake detector — fires when 4 transitions happen within 1 second
const int TILT_PIN = 7;
const int LED_PIN = 8;
const int BUZZER_PIN = 9;
const int SHAKE_THRESHOLD = 4; // transitions in the window
const unsigned long WINDOW_MS = 1000;
unsigned long stamps[SHAKE_THRESHOLD]; // ring buffer of recent transition times
int next = 0;
int lastTilt = HIGH;
void setup() {
pinMode(TILT_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
for (int i = 0; i < SHAKE_THRESHOLD; i = i + 1) stamps[i] = 0;
}
void fireAlarm() {
for (int i = 0; i < 3; i = i + 1) {
digitalWrite(LED_PIN, HIGH);
tone(BUZZER_PIN, 1500, 200);
delay(200);
digitalWrite(LED_PIN, LOW);
delay(100);
}
}
void loop() {
int tilt = digitalRead(TILT_PIN);
if (tilt != lastTilt) {
stamps[next] = millis();
next = (next + 1) % SHAKE_THRESHOLD;
lastTilt = tilt;
// Check the oldest stamp in the buffer
unsigned long oldest = stamps[next]; // next slot = oldest after wrap
if (oldest != 0 && millis() - oldest <= WINDOW_MS) {
fireAlarm();
for (int i = 0; i < SHAKE_THRESHOLD; i = i + 1) stamps[i] = 0;
}
}
}The trick is the ring buffer (stamps[] + next index that wraps with modulo) — the most recent 4 transition times are always remembered, and the oldest is one position after where we just wrote. If the oldest is less than a second old, that means all 4 transitions happened inside one second — a shake. After firing, the buffer is cleared so a continued shake doesn't keep retriggering. This same ring-buffer pattern shows up in serial parsers, audio buffers, and game-input handlers — it's an absolutely standard tool, and tilt switches are a friendly first reason to use it.
Recap 5 min
A tilt switch is a button gravity presses. Inside a small can, a ball bearing rolls onto two contacts when the can is tipped one way and off them when tipped the other way. Wire it like any L01-17 button — two leads, no polarity, INPUT_PULLUP — and read with digitalRead: HIGH for upright, LOW for tilted. Like real buttons, it bounces; reuse the L01-18 debounce patterns. Excellent for tip-over alarms, shake detectors and orientation indicators; not enough for fine-grained angle sensing (that's an accelerometer's job, Level 2). The whole concept reuses the digital-input pattern you already mastered for buttons; the new idea is that gravity is the user.
- Tilt switch (ball switch)
- A small two-lead component containing a ball bearing inside a sealed can. The ball completes a circuit when the can is tipped one way and breaks it when tipped the other. The simplest possible motion sensor.
- Mechanical switch
- A switch that opens or closes through a physical movement of parts — buttons (finger), tilt switches (gravity), reed switches (magnet), microswitches (lever). All read identically by the chip.
- Dead zone
- The range of orientations where the ball flickers between making and breaking contact, producing noisy readings. Always debounce a tilt switch.
- Ball bounce
- The brief period (a few milliseconds) when the ball is bouncing on the contacts before settling, producing rapid HIGH-LOW-HIGH-LOW noise. The L01-18 debounce trick fixes it.
- Ring buffer
- A small array used to track "the last N events" by wrapping the write index with modulo. After N writes the oldest is overwritten — automatic sliding-window memory. The shape used in the mini-challenge.
- Accelerometer (preview)
- A Level 2 sensor that reports the device's tilt and acceleration as continuous X/Y/Z values, not just open/closed. A tilt switch is its cheap one-bit ancestor.
Homework 5 min
The tip-over alarm. Build a sketch that pretends to be the tip-over feature of a desk lamp:
- Start in "armed" state: the LED on D8 stays steady on (indicating the device is upright and safe).
- If the device is tipped over (tilt switch fires LOW for at least 200 ms), enter "alarming" state:
- The LED on D8 starts flashing twice per second.
- The buzzer on D9 beeps at 1000 Hz for 100 ms every 500 ms.
- Print "ALARM — device tipped over" to the Monitor once when the alarm triggers.
- If the device is set back upright for at least 1 second, return to "armed" state — LED solid, buzzer silent, print "Re-armed" once.
This is a small state machine just like L01-23: two states, two transitions, each transition requires the new state to hold for a debounce window before firing.
Also: a design reflection on paper.
- Real shipping-package "tip indicators" don't use a microcontroller — they're a single passive component (often a small glass tube with coloured liquid) that turns colour permanently once tipped. What's the advantage of that approach over yours? What's the disadvantage? ____
- Your alarm needs a 200 ms hold to fire. What's the right number for that hold? Too short: the alarm fires on every desk bump. Too long: a real tip-over has finished before the alarm reacts. How would you decide the number empirically? ____
- The tilt switch detects "is the device upside down". It does not detect "is the device upright but moving". Suppose someone slides your lamp across the desk without tipping it — does your alarm fire? What sensor would catch that? ____
- Name three real-world products you've seen that probably have a tilt switch inside. (Hint: cheap kids' toys, bike lights, hotel TVs.) ____
Bring back next class:
- The saved
.inofile (call ittip-over-alarm). - A 30-second phone video showing the armed → tipped → alarming → reset → re-armed sequence.
- Your four written reflection answers, in your notebook.
Heads up for next class: L01-40 "The Potentiometer" introduces a sensor with no maths to derive — a built-in voltage divider with a knob attached. Three pins, no partner resistor needed. Turning the knob sweeps the analogRead value smoothly from 0 to 1023.