IoT lab viva notes

Tavish Gupta, 23BCP064

Experiment 2: LED and buzzer with digital, PWM and ultrasonic control

One output stage (an LED and an active buzzer) driven by three different inputs. The real subject is encoding: a level, a PWM duty cycle, and a distance carried inside a pulse width.

Objective

Part 1
Switch an LED and an active buzzer together at 0.5 Hz with digital output.
Part 2
Make the LED brightness (and buzzer drive) follow a knob: analog input → scaled → PWM output.
Part 3
Measure distance with an HC-SR04 and turn the LED and buzzer on when an object is within 200 cm.
Learn
digital vs analog input, ADC resolution, PWM, range conversion with map(), and time-of-flight measurement with pulseIn().

System

Part 1: a timerdelay(1000)Part 2: potentiometerA7, 0 to 5 VPart 3: HC-SR04TRIG 3, ECHO A7Arduino MEGAmap input to outputLED and buzzeron/off or PWMvoltagelevel/duty
Same output stage, three input sources. Each part is a different function from input to output.
PartInput encodingTransfer function in codeOutput encoding
1time (delay)toggle every 1000 mslevel: HIGH/LOW
2voltage → 10-bit ADC code 0 to 1023map(x, 0, 1023, 0, 255)PWM duty 0 to 255
3pulse width in µsdistance = t / 2 × 0.0343, then distance <= 200level: HIGH/LOW

Design decisions

Arduino MEGA instead of UNO

Why
More pins and 16 analog inputs; the code uses A7, which the UNO does not have.
Alternative
UNO with the pot on A0 to A5 and PWM pins chosen from 3, 5, 6, 9, 10, 11.
Switch when
When the pin count fits, the UNO is smaller and cheaper.

Active buzzer

Why
It contains its own oscillator, so plain digitalWrite(HIGH) makes a tone. No timing code needed.
Alternative
Passive buzzer driven by tone(pin, freq).
Switch when
When you need different pitches (the siren in Exp 3 needs a passive one).

10 kΩ potentiometer as a voltage divider

Why
Ends on 5 V and GND, wiper on the ADC: the wiper voltage is proportional to the shaft angle and the pot draws only 0.5 mA.
Alternative
A rotary encoder (digital, endless rotation) or buttons for up/down.
Switch when
Use an encoder when you need relative movement, no end stops, or no ADC noise.

Rescale with map()

Why
The ADC gives 0 to 1023 (10 bits) and analogWrite() takes 0 to 255 (8 bits); map() states the conversion explicitly.
Alternative
readVal / 4 or readVal >> 2 gives the same range with less arithmetic.
Switch when
Bit shifting when speed matters; map() when ranges are not powers of two.

HC-SR04 ultrasonic sensor

Why
Cheap, 2 to 400 cm range, works regardless of colour or ambient light, needs only two GPIOs and a timing function.
Alternative
IR distance sensor (analog, nonlinear, colour-sensitive) or a laser time-of-flight sensor such as VL53L0X (I²C, narrow beam, mm resolution).
Switch when
ToF for a narrow, precise measurement; IR for very short range; ultrasonic for cheap obstacle detection.

Measure the echo with pulseIn()

Why
One blocking call returns the pulse width in µs; no interrupt code.
Alternative
Interrupt on ECHO rising and falling edges, recording micros() each time.
Switch when
When the loop must not block for up to tens of milliseconds per reading.

Fixed 200 cm threshold, checked once per second

Why
The simplest decision rule; easy to verify in the simulator.
Alternative
Two thresholds (hysteresis), averaging several readings, or a smaller threshold such as 30 cm.
Switch when
Any real alarm, to stop flicker at the boundary and false triggers.

What we did

  1. Part 1: wired LED to pin 2 and buzzer to pin 4, each via 220 Ω; uploaded the sketch; checked the greeting on the Serial Monitor.

    Each load needs its own pin and its current limited. The greeting proves the sketch is running.

  2. Part 2: pot ends to 5 V and GND, wiper to A7; LED to pin 7, buzzer to pin 9.

    The ends define the 0 to 5 V span; pins 7 and 9 are PWM-capable on the MEGA, which analogWrite() needs.

  3. Turned the knob while watching the Serial Monitor.

    Printing raw and mapped values lets you verify the conversion by hand (163 → 40).

  4. Part 3: HC-SR04 VCC to 5 V, GND, TRIG to pin 3, ECHO to A7; LED to 12, buzzer to 7.

    TRIG is an output (we start a measurement); ECHO is an input (the sensor reports). Analog pins work as digital inputs.

  5. Moved a hand or set the simulator distance, and compared printed distances with reality.

    Checks the time-to-distance formula and the threshold.

Part 1: on/off control

Part 1 circuit.
Part 1 circuit.
  • Red wire from pin 2 to the LED branch, green wire from pin 4 to the buzzer branch (you can see both wires leave pins 2 and 4 on the header).
  • Each branch has a resistor in series and returns to GND (black wires).
  • Two independent outputs, written in the same pass, so they switch together.

Part 1: LED and buzzer

22 lines, exactly as in your lab file

int ledPin = 2;int buzzPin = 4; void setup() {    // put your setup code here, to run once:    Serial.begin(9600);    Serial.println("Hello Ardino!!");     pinMode(ledPin, OUTPUT);    pinMode(buzzPin, OUTPUT);} void loop() {    // put your main code here, to run repeatedly:    digitalWrite(ledPin, HIGH);    digitalWrite(buzzPin, HIGH);    delay(1000);     digitalWrite(ledPin, LOW);    digitalWrite(buzzPin, LOW);    delay(1000);}
  1. Lines 1 to 2
    Two outputs.
  2. Lines 6 to 7
    Banner on start. The typo is inside a string literal and has no effect.
  3. Lines 9 to 10
    Both pins driven.
  4. Lines 15 to 17
    Both HIGH, hold 1 s. The active buzzer’s oscillator runs while powered.
  5. Lines 19 to 21
    Both LOW, hold 1 s. Period 2 s, 0.5 Hz.
Simulation during the HIGH half: LED lit, buzzer active.
Simulation during the HIGH half: LED lit, buzzer active.

Part 2: potentiometer to PWM

5 V A7 wiper Turning the knob moves the wiperone end → 0 V → 0middle → 2.5 V → ~512other end → 5 V → 1023then map() to 0 … 255 for analogWrite
The pot is a voltage divider: the wiper voltage is a linear function of the shaft position.

The chain is: angle → wiper voltage → ADC code (0 to 1023) → map() → duty (0 to 255) → average output voltage. map() computes (x − in_min) × (out_max − out_min) / (in_max − in_min) + out_min in integer arithmetic, so the fraction is truncated, not rounded.

163 maps to 40.
Part 2 circuit.
Part 2 circuit.
  • Pot: red wire to 5 V, black to GND, green from the middle pin (wiper) to A7 on the analog header.
  • LED (via resistor) and buzzer on the PWM header, pins 7 and 9.

Part 2: potentiometer

26 lines, exactly as in your lab file

int ledPin = 7;int buzzPin = 9;int potPin = A7;int readVal;int mapVal; void setup() {    // put your setup code here, to run once:    Serial.begin(9600);    Serial.print("HEllo");     pinMode(buzzPin, OUTPUT);    pinMode(potPin, INPUT);} void loop() {    // put your main code here, to run repeatedly:    readVal = analogRead(potPin);    Serial.println(readVal);     mapVal = map(readVal, 0, 1023, 0, 255);    Serial.println(mapVal);     analogWrite(ledPin, mapVal);    analogWrite(buzzPin, mapVal);}
  1. Lines 1 to 3
    PWM pins 7 and 9; analog input A7 (MEGA only).
  2. Lines 4 to 5
    Raw and scaled values, global so they persist (they would work as locals too).
  3. Line 10
    print without a newline, so the first reading is glued onto it (“HEllo163”).
  4. Lines 12 to 13
    No pinMode for ledPin: analogWrite() sets output mode itself. INPUT on the analog pin is redundant but harmless.
  5. Lines 18 to 19
    One ADC conversion (about 0.1 ms on AVR), printed.
  6. Lines 21 to 22
    Integer rescale, printed. The monitor therefore alternates raw and mapped values.
  7. Lines 24 to 25
    Load the same duty into both PWM channels. No delay: the loop rate is limited by how fast Serial.println can push bytes at 9600 baud.
Your Part 2 output.
Your Part 2 output.
  • The log alternates 163 and 40: raw ADC code, then the mapped duty.
  • Check: 163 × 255 / 1023 = 40.63 → truncated to 40. This proves the mapping is integer map().
  • 163 counts × 4.9 mV ≈ 0.80 V on the wiper, about 16 % of the knob’s travel.
  • The LED in the screenshot is partly lit: about 40/255 ≈ 16 % duty.

Part 3: ultrasonic distance threshold

The sensor converts distance into time: after a 10 µs TRIG pulse it emits eight 40 kHz cycles and holds ECHO HIGH until the echo returns. Distance = speed of sound × time / 2, since the sound travels out and back. At about 20 °C sound covers 343 m/s = 0.0343 cm/µs.

TRIG10 µs burst8 × 40 kHz ECHO pulseIn(echoPin, HIGH) measures this width = time there and back distance = duration / 2 × 0.0343 cm
TRIG, the burst, and the ECHO pulse whose width is the round-trip time.
10620 µs gives 182 cm.
Part 3 circuit.
Part 3 circuit.
  • HC-SR04 pins left to right: VCC (red, to 5 V), TRIG (to pin 3), ECHO (to A7), GND (black).
  • LED via resistor to pin 12, buzzer via resistor to pin 7.
  • ECHO goes to an analog pin used as a digital input; the code never calls analogRead() on it.

Part 3: ultrasonic alert

42 lines, exactly as in your lab file

int ledPin = 12;int trigPin = 3;int echoPin = A7;int buzzPin = 7;int duration;int distance; void setup() {    // put your setup code here, to run once:    Serial.begin(9600);    Serial.println("Hello");     pinMode(trigPin, OUTPUT);    pinMode(echoPin, INPUT);    pinMode(ledPin, OUTPUT);} void loop() {    // put your main code here, to run repeatedly:    digitalWrite(trigPin, LOW);    delayMicroseconds(2);    digitalWrite(trigPin, HIGH);    delayMicroseconds(10);    digitalWrite(trigPin, LOW);    delayMicroseconds(2);     duration = pulseIn(echoPin, HIGH);     distance = duration / 2 * 0.0343;    Serial.println(distance);     if (distance <= 200) {        digitalWrite(ledPin, HIGH);        digitalWrite(buzzPin, HIGH);        delay(1000);    }    else {        digitalWrite(ledPin, LOW);        digitalWrite(buzzPin, LOW);        delay(1000);    }}
  1. Lines 1 to 4
    Pin map: two outputs, the trigger output, and the echo input.
  2. Lines 5 to 6
    16-bit int on AVR: −32768 to 32767. Relevant to the overflow limit below.
  3. Lines 13 to 15
    TRIG out, ECHO in, LED out. buzzPin is never set to OUTPUT; see Limits.
  4. Lines 20 to 21
    Ensure a clean LOW so the next edge is a proper rising edge.
  5. Lines 22 to 23
    The 10 µs trigger pulse the datasheet requires.
  6. Line 27
    Blocks until ECHO rises, then times how long it stays HIGH, in µs. Returns 0 if nothing arrives within the default 1 s timeout.
  7. Line 29
    Integer division first, then a float multiply, then truncation into int. 10620 µs → 5310 → 182.13 → 182 cm.
  8. Line 30
    Report every reading.
  9. Lines 32 to 35
    Within 200 cm: both outputs HIGH, wait 1 s.
  10. Lines 37 to 39
    Otherwise both LOW, wait 1 s. So the system samples at about 1 Hz.
Part 3 on hardware.
Part 3 on hardware.
  • A hand in front of the sensor; the LED on the breadboard is lit.
  • Proves the threshold path: distance under 200 cm → LED HIGH.

Limits and redesign

  • No hysteresis: an object sitting near 200 cm makes the alert flicker. Use two thresholds (on below 190, off above 210).
  • One reading decides: a single bad echo triggers the alarm. Take the median of 3 to 5 readings and ignore 0.
  • Temperature: 0.0343 assumes about 20 °C; speed of sound is roughly 331 + 0.6 × T m/s.
  • Blocking: pulseIn() plus delay(1000) means the board can do nothing else. An interrupt-driven echo timer and millis() scheduling remove both.

Say this in the viva

Viva questions

Why

Why divide the echo time by 2?

ECHO stays HIGH for the round trip: to the object and back. Distance is one way.

Why does map() give 40 for 163 and not 41?

It uses integer arithmetic: 163 × 255 / 1023 = 40.63, and the fraction is truncated.

Why are pins 7 and 9 used in Part 2?

They are PWM-capable on the MEGA; analogWrite() only produces a variable duty on PWM pins.

Why an active buzzer in this experiment?

It only needs on/off, and an active buzzer makes sound from DC without any timing code.

What if

What if the object is 5 m away?

Beyond the sensor’s range: weak or no echo, pulseIn() may return 0 (prints 0 cm, which the code treats as “within 200”, a false alarm) or an unreliable value.

What if you write analogWrite() to pin 8?

Pin 8 is PWM on the MEGA (pins 2 to 13 are), so it works there. On an UNO, pin 8 is not PWM and would only go fully on or off.

What if the room is at 40 °C?

Sound travels faster (about 355 m/s), so the true distance is slightly larger than the reading; the code reads about 3 % short.

Design

How would you make this a parking sensor?

Lower threshold (20 to 50 cm), several distance bands with faster beeping as it gets closer, median filtering, and non-blocking timing so beeps and measurements interleave.

How would you measure distance without blocking?

Attach a pin-change interrupt to ECHO, record micros() on the rising and falling edges, and compute the distance in loop() when a new measurement is ready.