class 13 · unit II · motion, position, force and tactile sensors
Which way is down, where am I, who touched me?
The IMU is the workhorse of TinyML. Position sensors span millimetres to the whole planet. And touch is often free on the chip you already have.
Theory runs to slide 11; the lab is one block at the end (slides 12 to 15). Students keep the MPU6050 wired from Class 11; add two strips of foil for the touch pads.
last class's exit ticket
15 frames a second of VGA RGB565.
640 × 480 × 2 B × 15 = 9,216,000 B/s ≈ 8.8 MB/s
And each 600 KB frame is bigger than all of SRAM. Better: greyscale, smaller frames, fewer frames, or count only when something moves.
Today's sensors are the opposite: a few numbers a hundred times a second. Cheap to move, cheap to store, and full of information.
Take one answer that proposed waking the camera only on motion: that is today's IMU, or Class 14's PIR.
Turn your phone sideways. How did it know?
rotate
the screen
gravity pulls differently on the accelerometer
count
your steps
a repeating pattern in acceleration, about twice a second
point
the map arrow
magnetometer plus gyroscope
raise
to wake
a tiny model on the motion sensors, always on
The last one is TinyML in your pocket: a gesture classifier running on a motion sensor, all day, on almost no power.
Many phones run raise-to-wake on a low-power sensor hub rather than the main processor; that is Class 18's multi-device idea inside one phone.
An IMU is up to three sensors, each with three axes.
sensor
measures
when still
weakness
accelerometer
linear acceleration, gravity included
about 1 g, pointing down
noisy; cannot tell tilt from motion
gyroscope
rotation rate, degrees per second
about zero
small offsets add up: drift
magnetometer
magnetic field: a compass
Earth's field
fooled by nearby metal and motors
The MPU6050 is 6-axis: accelerometer and gyroscope, no magnetometer. Parts with all three are called 9-axis.
The axis directions follow the MPU6050 datasheet's orientation diagram; check the dot on your module, since breakout boards mount the chip differently.
try it live
A still accelerometer is a tilt sensor, because gravity never switches off.
tilt
motion
Black arrow: gravity, 1 g straight down. Red and blue: what the board's x and z axes feel. Tilt = atan2(ax, az). Then switch on "pushed sideways": the accelerometer cannot tell a push from a tilt, so the estimate is wrong while it moves. That is why we add a gyroscope.
try it live · sensor fusion
The accelerometer is noisy. The gyroscope drifts. Blend them.
Simulated 10 seconds at 100 Hz: the board tilts to 40°, then back to 10°. The gyroscope has a small constant bias, so integrating it drifts; the accelerometer is noisy, with a burst of shaking near the middle. The complementary filter trusts the gyro for quick changes and the accelerometer for the long-term level. Dashed: the true angle. Name sensor fusion here; Unit III returns to combining sensors.
position
Where is it? The answer depends on how far you need to see.
Distance measured, log scale. Ranges and accuracies are rough orders of magnitude for common low-cost parts. NavIC is India's regional satellite navigation system.
Rotary encoders measure the position of a shaft, not a distance, so they are not on the chart: name them for robot wheels and motors. mmWave radar returns properly in Class 14.
force
A load cell is a metal bar that bends a tiny amount.
load cell
Accurate weight. Smart shelves, beehive scales, a bed that knows someone got up.
force-sensitive resistor (FSR)
Cheap and imprecise: "pressed or not". Chair cushions, posture, grip.
Class 10's chain again: the bar is the transducer, the bridge is conditioning, the HX711 is the ADC. HX711 boards are common and cheap; they are not in our kit.
touch
A finger adds capacitance. The chip can measure it directly.
The ESP32-S3 has built-in capacitive touch channels on several of its pins. A strip of foil and a wire make a button with no extra part, no moving part, and a sealed case.
Deciding "touched or not" is a tiny classifier with one feature. A threshold usually works; a model helps when you want swipes, or to ignore water drops.
On the S3 the reading rises when touched. On the original ESP32 it falls. Always look at your own numbers first.
The trace is illustrative. The light brush is the interesting case: is it a touch? This is where Class 8's "cheapest thing first" meets a real decision. The S3's touch-capable pins are GPIO 1 to 14; confirm on your board's pin map.
standing
leaning forward
A grid of pressure sensors makes a picture of touch.
A smart insole with a few hundred pressure points produces a small image, many times a second.
And small images are what Class 7's CNNs are good at: gait analysis, fall risk, posture, a robot gripper that knows it is slipping.
The same idea as the spectrogram in Class 8: turn a signal into an image, then use image tools.
Simulated pressure maps on a 20 × 44 grid. Ask what label you would train on: standing, walking, leaning, about to fall.
our running example
Two of today's sensors make the doorbell better for almost nothing.
a capacitive pad as the button
No moving parts, no gap for rain to get in, and the chip already has the sensor. A long press and a short press can mean different things.
an accelerometer for tamper alerts
Someone prying the doorbell off the wall is a sudden tilt and shock. A threshold, or a tiny model, sends an alert before the camera is lost.
Neither needs a big model. Both are always on, nearly free, and make the product harder to break.
End of theory. Students should already have the MPU6050 wired from Class 11; hand out foil strips and move to the lab block.
lab · teams of four
Three parts: tilt the LED, build a touch button, watch the gyro drift.
30:00
part
ESP32-S3
MPU6050 SDA / SCL
GPIO 8 / GPIO 9, as in Class 11
MPU6050 VCC / GND
3V3 / GND
foil pad A
GPIO 4 (touch-capable)
foil pad B
GPIO 5 (touch-capable)
RGB LED
on the board, no wiring
A · tilt → colour
accelerometer only, about 10 minutes
B · foil touch button
pick a threshold from your own numbers, about 10 minutes
C · gyro drift, 60 seconds
leave the board perfectly still and integrate, about 5 minutes
Tape the foil strips to the desk and push a jumper wire against each. The onboard RGB LED is driven by the core's RGB_BUILTIN definition; its GPIO differs between DevKitC-1 revisions, which is why the code does not hard-code it.
// Part A · tilt from the accelerometer → LED colour// Part C · integrate the still gyroscope and watch it drift#include<Adafruit_MPU6050.h>
Adafruit_MPU6050 mpu;
float gyroAngle = 0; unsigned long last;
voidsetup() {
Serial.begin(115200);
Wire.begin(8, 9); mpu.begin();
last = micros();
}
voidloop() {
sensors_event_t a, g, t;
mpu.getEvent(&a, &g, &t);
float tilt = atan2(a.acceleration.x, a.acceleration.z) * 180 / PI;
float dt = (micros() - last) / 1e6; last = micros();
gyroAngle += g.gyro.y * dt * 180 / PI; // rad/s → degrees
Serial.printf("tilt %6.1f gyro %7.2f\n", tilt, gyroAngle);
int r = constrain(abs(tilt) * 255 / 90, 0, 255);
rgbLedWrite(RGB_BUILTIN, r / 4, (255 - r) / 4, 0); // dimmed
delay(20);
}
lab · parts A and C
Tilt the board. Then leave it alone.
A. Tilt slowly: does the angle match? Now shake it while level: what does "tilt" say?
C. Press reset, put the board flat, do not touch it for 60 s. The gyro column should stay at 0. Does it?
Green when level, red when tilted. If your axes are swapped, use a.acceleration.y and g.gyro.x.
rgbLedWrite and RGB_BUILTIN are in Arduino-ESP32 core 3.x; on core 2.x the same call is neopixelWrite. The gyro axis that matches the tilt depends on how the module sits on the breadboard. Drift of a few degrees per minute or more is normal for an uncalibrated MPU6050; that is the point of Part C.
// Part B · two foil pads on the S3's touch pinsconst int PAD_A = 4, PAD_B = 5;
float baseA, baseB;
voidsetup() {
Serial.begin(115200);
delay(500); // hands off while it starts
baseA = touchRead(PAD_A);
baseB = touchRead(PAD_B);
}
voidloop() {
float a = touchRead(PAD_A), b = touchRead(PAD_B);
float riseA = 100 * (a - baseA) / baseA; // % above baselinefloat riseB = 100 * (b - baseB) / baseB;
Serial.printf("A %+6.1f%% B %+6.1f%%\n", riseA, riseB);
// your turn: choose THRESHOLD from the numbers you see// if (riseA > THRESHOLD) ...
delay(50);
}
lab · part B
Find your own threshold.
Watch the percentages with no hand, a hovering hand, a light touch and a firm press.
Pick a threshold, add the if, and light the LED on a touch. Then try through a sheet of paper, and with a damp finger.
Two pads? Touch A then B quickly: you have built a swipe.
Readings rise on touch on the S3. Teams will pick different thresholds; ask why (different foil sizes, wire lengths, people). That variation is exactly why calibration at start-up matters.
lab · fill these six boxes as a team
Your board, your numbers.
A · tilt at rest
flat, and on its side, in degrees
A · shake while level
what did tilt read? why?
B · touch readings
% rise: hover, light, firm
B · your threshold
and does it work through paper?
C · gyro after 60 s
degrees of drift with no motion
verdict
which sensor would you trust for a 10-minute tilt reading, and why?
The verdict box should arrive at the complementary filter on its own: the accelerometer for the long-term level, the gyroscope for quick changes.
exit ticket · on paper, before you leave
A fitness band must tell walking from cycling, worn on the wrist. Which IMU sensors and axes would you use, and what does each tell you?
Next class: light, radar, gas, heartbeats. The remaining sensor families, and how to read a datasheet you have never seen.
Good answers: the accelerometer's rhythm (steps near 2 per second show strongly on the wrist; cycling does not swing the arm), the gyroscope's rotation pattern, and the overall energy. Cycling on a rough road is the hard case; ask what extra data would help.