~90 min. Wire the HC-SR04 ultrasonic distance sensor. Read distance in centimeters. Trigger an LED or buzzer when something gets too close.
Goal: read a specialized sensor with a protocol of its own; convert sensor data to a real-world quantity (centimeters)
Estimated time: 90 minutes
Prerequisites: lab 8.1 (digital I/O); lab 11.1 (Serial debug)
Steps
Step 1: Identify the HC-SR04 pins (5 min)
The HC-SR04 has 4 pins: VCC (+5 V), Trig, Echo, GND. Label them visually; they are usually printed on the board
Step 2: Wire the sensor (15 min)
- VCC → R4's 5V pin
- GND → R4's GND
- Trig → R4's pin 7
- Echo → R4's pin 8
Pins 7 and 8 are arbitrary digital pins; pick others if you prefer. Just make sure they are digital-only (no PWM concerns; this is purely digital pulse timing)
Step 3: Write the basic read sketch (25 min)
const int TRIG_PIN = 7;
const int ECHO_PIN = 8;
void setup() {
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
Serial.begin(9600);
}
void loop() {
// Send 10us trigger pulse
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Read echo pulse duration (in microseconds)
unsigned long duration = pulseIn(ECHO_PIN, HIGH, 30000); // 30 ms timeout
// Convert to centimeters: speed of sound = 343 m/s = 29.1 us/cm
// pulse is round-trip, so divide by 2
float distance_cm = duration / 58.3;
Serial.print("Duration: ");
Serial.print(duration);
Serial.print(" us Distance: ");
Serial.print(distance_cm);
Serial.println(" cm");
delay(250);
}
Upload. Open Serial Monitor. You should see distance readings. Move your hand toward and away from the sensor; the distance updates
Step 4: Calibrate against a ruler (15 min)
Place objects at known distances (10 cm, 20 cm, 50 cm, 100 cm). Compare the sensor's reading to the ruler. The HC-SR04 is typically accurate to ±1 cm at short ranges, ±2-3 cm at longer ranges
Note any failure modes: very close (< 2 cm; sensor's minimum), very far (> 400 cm; sensor's maximum), oblique surfaces (echo bounces away), soft surfaces (echo is absorbed)
Step 5: Add a "too close" alert (20 min)
Add an LED on pin 9. Light it when distance < 20 cm:
const int LED_PIN = 9;
void setup() {
// ... existing code ...
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// ... existing read code ...
if (distance_cm > 0 && distance_cm < 20) {
digitalWrite(LED_PIN, HIGH);
Serial.println(" ALERT: too close!");
} else {
digitalWrite(LED_PIN, LOW);
}
delay(250);
}
Upload. Move objects in front of the sensor; the LED turns on inside 20 cm
Step 6: Document (10 min)
Lab notebook: distance vs reading calibration table. Failure modes you observed. Reflect on what changing the threshold (10 cm? 50 cm? 5 cm?) would mean for an actual application
Expected output
- Working distance sensor reading distance in cm
- Calibration against ruler
- "Too close" LED alert at threshold
Common pitfalls
- Wrong pin assignment for Trig vs Echo: Trig is OUTPUT (you send the pulse); Echo is INPUT (you receive the response). Reversed = sketch hangs or gets garbage
- Timeout too short: pulseIn(ECHO_PIN, HIGH, X) where X is too small will return 0 when the target is far away. 30000 (30 ms) handles up to ~5 m
- Sound interference: ultrasonic sensors can interfere with each other or pick up echoes from walls. Test in an open area first
Stretch (optional)
- Replace LED with the buzzer (with transistor switch if buzzer is too loud for direct pin drive). The buzzer beeps faster as the object gets closer (proximity alarm)
- Use the distance to control LED brightness via PWM (close = bright, far = dim). Map distance (0-200 cm) to brightness (255-0)
- Read three different sensors from your kit (temperature, humidity, motion, etc.) following the same pattern: protocol → read → convert → use
Lab 12.1 v0.1. The first specialized sensor. The pattern generalizes to every other sensor you will encounter.