10  Visual and Audio Actuators

actuators
visual
audio

10.1 Start With the Story

Imagine a leak detector hidden under a sink. A dashboard notification may be useful later, but the device needs a local story too: flash, beep, show status, and make the warning impossible to miss in the place where the problem happens.

Visual and audio actuators turn invisible system state into human feedback. Choose LEDs, displays, buzzers, tones, and patterns around attention, power, environment, and how quickly a person must understand the message.

In 60 Seconds

Visual actuators (LEDs, LCD/OLED displays, addressable LED strips) and audio actuators (passive and active buzzers) provide essential user feedback in IoT devices. LEDs are controlled via PWM for brightness dimming, addressable strips like NeoPixels allow individual pixel control over a single data wire, and passive buzzers generate variable-frequency tones for alerts and melodies.

Phoebe the physics guide

Phoebe’s Why

This chapter’s 8-bit PWM dimmer and 5 kHz LED switching rate are not arbitrary firmware settings; they sit against two hard physical limits from information theory. First, chopping a continuous brightness command into 256 discrete duty-cycle codes is exactly the same rounding operation an ADC performs on a sensor voltage – it leaves a quantization “noise floor” that a formula can predict, and here the true sensor doing the rounding-back-out is the human eye, whose own brightness discrimination has a floor too. Second, switching an LED on and off is itself a sampled process from the point of view of anything that samples light in time – your eye barely notices, but a rolling-shutter camera samples at its own frame rate, and if the PWM frequency and the camera’s sample rate are not chosen carefully, the fast switching folds down into a slow, very visible beat – the same spectral-folding failure a badly chosen ADC sample rate produces on a sensor signal.

The Derivation

Quantizing an \(N\)-bit duty-cycle code over full-scale range \(\mathrm{FSR}\) leaves a step and a noise floor:

\[q = \frac{\mathrm{FSR}}{2^{N}}, \qquad \text{noise power} = \frac{q^{2}}{12}\]

For a full-scale signal, the ratio of signal power to that noise floor reduces to the standard ADC/DAC result (the \(\mathrm{FSR}\) terms cancel):

\[\mathrm{SNR}(\mathrm{dB}) = 6.02N + 1.76\]

Any process that samples a time-varying signal at rate \(f_s\) folds an input component at \(f_{in}\) down to an aliased frequency inside the baseband:

\[f_{alias} = \left| f_{in} - \mathrm{round}\!\left(\frac{f_{in}}{f_s}\right) f_s \right|\]

which is zero only when \(f_s \geq 2f_{in}\) places \(f_{in}\) outside the fold range entirely – the Nyquist criterion.

Worked Numbers: This Chapter’s Own 8-bit, 5 kHz PWM

  • This chapter’s own 8-bit brightness code (\(N=8\)): \(\mathrm{SNR}=6.02\times8+1.76=49.9\) dB. Quantization step at the chapter’s own \(5\) V driver, chapter’s own \(1/255\) convention: \(q=5/255=0.0196\) V, matching the chapter’s own figure; rms noise floor \(q/\sqrt{12}=0.00566\) V \(=5.66\) mV.
  • Tying it to the transducer that actually reads it – the eye: a catalog-typical luminance just-noticeable-difference (Weber fraction) is about \(1\%\). The 8-bit code step is \(1/255=0.392\%\) of full scale – already about \(2.5\times\) finer than the eye’s own discrimination floor, so more PWM bits could not buy a visibly smoother fade; the eye’s transduction physics, not the PWM resolution, is the limiting stage.
  • This chapter’s own 5 kHz LED PWM sampled by a catalog-typical camera frame rate: \(f_{alias}=|5000-\mathrm{round}(5000/f_s)\,f_s|\) gives \(8.00\) Hz at \(24\) fps, \(0.00\) Hz at \(25\) fps, \(10.0\) Hz at \(30\) fps, and \(20.0\) Hz at \(60\) fps.
  • Honest finding: a \(5\) kHz PWM rate is far above anything the naked eye resolves, yet three of these four common frame rates fold it down into an \(8\)-\(20\) Hz beat – squarely inside the range a viewer does notice as banding on video. That is a real, reported LED-flicker-on-camera failure mode, and the fix is a Nyquist-style one: pick a PWM frequency (or a filtering scheme) that does not fold into a low beat against the target frame rates, not just one that is “fast.”

Learning Objectives

After completing this chapter, you will be able to:

  • Configure PWM parameters to dim LEDs across 256 brightness levels
  • Program addressable RGB LED strips (NeoPixels/WS2812B) for independent pixel control
  • Explain why LED matrix blocks use driver ICs such as MAX7219/MAX7221 instead of direct GPIO control
  • Interface LCD and OLED displays using I2C/SPI communication protocols
  • Generate tones and melodies with passive buzzers using frequency modulation
  • Design multi-modal visual and audio feedback systems for IoT applications
Quick Check: Feedback Modality Selection

Think of how a microwave beeps when your food is ready, or how a traffic light changes color to tell you when to stop or go. Visual actuators (like LEDs and screens) and audio actuators (like buzzers) are the ways IoT devices communicate with people. They turn invisible data into something you can see or hear, making smart devices feel responsive and helpful.

Chapter Roadmap

This chapter has four linked stops:

  1. First you choose local feedback channels: LEDs, displays, buzzers, or combinations.
  2. Then you control LEDs with current limiting, PWM brightness, RGB channels, and addressable pixel power budgets.
  3. Next you move from lights to information displays: matrix drivers, LCD character layouts, and OLED frame buffers.
  4. Finally you design audible and multi-modal alerts, then check the selection against power, noticeability, and environment.

Checkpoints recap the main decisions as you go. Existing calculators, quizzes, and deep dives are optional breathers when you want to test the numbers.

10.2 LED Control

LEDs (Light Emitting Diodes) are the simplest visual actuators, used for indicators, status lights, and ambient lighting.

Calculate the required series resistor for safe LED operation:

How It Works: LED Brightness Control via PWM

You might think dimming an LED means reducing voltage, but that’s not how it works. Here’s the trick:

Step 1: On/Off at High Speed - Instead of lowering voltage (which would change LED color), the microcontroller rapidly switches the LED fully ON and fully OFF – thousands of times per second (typically 1-20 kHz).

Step 2: Vary the Duty Cycle - - 100% brightness = LED on 100% of the time - 50% brightness = LED on 50%, off 50% (alternating) - 10% brightness = LED on 10%, off 90%

Step 3: Your Eye Averages It - The switching happens so fast (>500 Hz) that your eye perceives a smooth brightness level, not flickering. It’s like spinning a fan – individual blades blur into a circle.

Real-World Analogy: Imagine a light switch you flick on and off 1,000 times per second. If you keep it on 70% of the time (on for 0.7ms, off for 0.3ms in each 1ms cycle), your eye sees 70% brightness – even though the LED is always either fully ON or fully OFF, never “dim.”

Why This Method?

  • Maintains LED color accuracy (full voltage = correct wavelength)
  • No heat dissipation in resistors (efficient)
  • Fine brightness control (8-bit PWM = 256 levels from 0-255)
  • Works with any LED without special dimming circuits

Calculate power consumption and energy savings for LED brightness control:

Example: At 50% PWM brightness (duty cycle = 0.5), an LED with forward voltage \(V_f = 2.1\) V and \(I_f = 20\) mA appears half as bright and uses half the power. Average current is \(I_{avg} = 0.5 \times 20 = 10\) mA, so power is \(P = V_f \times I_{avg} = 2.1 \times 0.01 = 0.021\) W. Over 24 hours, this saves \(E = (0.042 - 0.021) \times 24 = 0.5\) Wh compared to full brightness.

10.2.1 Basic LED with PWM Brightness

#define LED_PIN 25

void setup() {
  // Configure PWM for LED dimming
  ledcSetup(0, 5000, 8);  // Channel 0, 5kHz, 8-bit resolution
  ledcAttachPin(LED_PIN, 0);
}

void loop() {
  // Fade in
  for (int brightness = 0; brightness <= 255; brightness++) {
    ledcWrite(0, brightness);
    delay(10);
  }

  // Fade out
  for (int brightness = 255; brightness >= 0; brightness--) {
    ledcWrite(0, brightness);
    delay(10);
  }
}

10.2.2 RGB LED Control

// RGB LED pins (common cathode)
#define RED_PIN 25
#define GREEN_PIN 26
#define BLUE_PIN 27

void setup() {
  // Configure PWM for each color channel
  ledcSetup(0, 5000, 8);  // Red
  ledcSetup(1, 5000, 8);  // Green
  ledcSetup(2, 5000, 8);  // Blue

  ledcAttachPin(RED_PIN, 0);
  ledcAttachPin(GREEN_PIN, 1);
  ledcAttachPin(BLUE_PIN, 2);
}

void setColor(int red, int green, int blue) {
  ledcWrite(0, red);
  ledcWrite(1, green);
  ledcWrite(2, blue);
}

void loop() {
  setColor(255, 0, 0);    // Red
  delay(1000);
  setColor(0, 255, 0);    // Green
  delay(1000);
  setColor(0, 0, 255);    // Blue
  delay(1000);
  setColor(255, 255, 0);  // Yellow
  delay(1000);
  setColor(0, 255, 255);  // Cyan
  delay(1000);
  setColor(255, 0, 255);  // Magenta
  delay(1000);
  setColor(255, 255, 255);// White
  delay(1000);
}
Try It: RGB Color Mixer
Motor MaxCheckpoint: LED Feedback

You now know:

  • A visible indicator still needs electrical limits: the resistor calculator uses supply voltage, LED forward voltage, and desired current.
  • PWM controls perceived brightness by changing duty cycle, not by lowering the LED’s forward voltage.
  • The RGB examples use three PWM channels with 8-bit values from 0 to 255, so color choice and current budget move together.

With single LEDs and RGB packages under control, the next question is how to scale beyond three channels without spending one GPIO per color.

10.3 Addressable LED Strips (NeoPixel/WS2812B)

Addressable LEDs allow individual control of each LED in a strip using a single data wire.

Calculate power requirements for addressable LED strips:

Note: WS2812B LEDs draw approximately 60mA at full white (all three RGB channels at maximum). Single colors draw ~20mA. Always add a 20% safety margin to your power supply rating.

Check Arithmetic carried through Result to use in the review
Single LED full power 2.1 V x 0.020 A = 0.042 W One full-bright indicator is about 42 mW.
50% PWM LED current 0.50 x 20 mA = 10 mA; 2.1 V x 0.010 A = 0.021 W The same LED is about 21 mW before driver losses.
24-hour PWM saving (0.042 W - 0.021 W) x 24 h = 0.504 Wh Round at the end: about 0.5 Wh saved per LED-day.
5 kHz PWM timing 1 / 5000 = 0.0002 s = 0.2 ms; 0.2 ms x 0.50 = 0.1 ms A 50% command is roughly 100 microseconds on and 100 microseconds off.
8-bit brightness step 1 / 255 = 0.0039216; 5 V x 0.0039216 = 0.0196 V One code step is about 0.392%, or 19.6 mV of ideal average on a 5 V LED driver.
30-pixel full-white strip 30 x 60 mA = 1800 mA = 1.8 A; 5 V x 1.8 A = 9 W Full-white worst case needs a supply sized above 1.8 A.
20% supply margin 1.8 A x 1.20 = 2.16 A Choose at least a 2.16 A 5 V supply for the full-white 30-pixel case.
Code brightness limit 50 / 255 = 0.1961; 1.8 A x 0.1961 = 0.353 A; 5 V x 0.353 A = 1.76 W The code’s setBrightness(50) keeps a full-white frame near 0.35 A, but release evidence should still check startup and fault cases.

The audit conclusion is bounded: PWM reduces average LED power, and the strip code greatly lowers the steady full-white current. It does not remove the need to size wiring, ground return, fuse behavior, and supply margin for the highest credible visual state.

#include <Adafruit_NeoPixel.h>

#define LED_PIN 18
#define NUM_LEDS 30

Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.setBrightness(50);  // 0-255 (limit current draw)
  strip.show();
}

void loop() {
  rainbow(10);                                // Cycle all hues
  colorWipe(strip.Color(0, 255, 0), 50);     // Green wipe
  colorWipe(strip.Color(127, 0, 0), 50);     // Red wipe
}

// Animate a rainbow across the strip
void rainbow(int wait) {
  for (long hue = 0; hue < 65536; hue += 256) {
    for (int i = 0; i < strip.numPixels(); i++) {
      int pixelHue = hue + (i * 65536L / strip.numPixels());
      strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
    }
    strip.show();
    delay(wait);
  }
}

// Fill strip one pixel at a time
void colorWipe(uint32_t color, int wait) {
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
    strip.show();
    delay(wait);
  }
}

10.4 LED Matrices and Driver ICs

An LED matrix block packs many ordinary LEDs into a row/column grid. An 8x8 matrix has 64 emitters, but the package usually exposes row and column pins rather than 64 separate LED pairs. The controller lights a pattern by selecting one row or column at a time fast enough that the eye sees a stable image. That multiplexing saves pins, but it creates two practical problems: the firmware must refresh the matrix continuously, and the current peaks through the active row or column must stay inside the matrix and driver ratings.

This is why small LED matrix kits usually include more than the visible block. A review should identify the matrix block, socket or carrier PCB, headers, passive parts, and the display-driver IC before treating the kit as “just LEDs.” The driver owns the repetitive refresh and current-limited switching while the microcontroller sends compact display data.

The MAX7219/MAX7221 family is a common example. It sits between the MCU and the matrix: DIN receives serial data, CLK clocks bits in, LOAD or CS latches a command, and DOUT can pass data to another driver. On the display side, the DIG0 through DIG7 pins select rows or digits, while SEG A through SEG G and SEG DP drive the eight column or segment lines. V+ and GND power the chip, and the ISET resistor sets the peak segment current.

For a raw 8x8 LED matrix, leave decode mode off and write row or column bit patterns directly. The register addresses are part of the wiring evidence: 0x01 through 0x08 hold the eight digit or row data bytes, 0x09 controls decode mode, 0x0A controls intensity, 0x0B sets the scan limit, 0x0C leaves shutdown mode, and 0x0F enables or disables display test. A first proof can write a diagonal or single-row sweep, then record whether the image is rotated, mirrored, or missing rows.

#include <LedControl.h>

#define DIN_PIN 23
#define CLK_PIN 18
#define CS_PIN 5

LedControl matrix(DIN_PIN, CLK_PIN, CS_PIN, 1);  // one MAX7219 device

void setup() {
  matrix.shutdown(0, false);   // leave shutdown mode
  matrix.setIntensity(0, 4);   // 0-15 brightness range
  matrix.clearDisplay(0);
}

void loop() {
  for (int row = 0; row < 8; row++) {
    matrix.clearDisplay(0);
    matrix.setRow(0, row, 1 << row);  // diagonal orientation test
    delay(150);
  }
}

The chip interface is small, but it is still a protocol. Each update is a 16-bit instruction: one address byte selects the target register and one data byte supplies the value. CLK advances each bit, DIN carries the bit value, and LOAD or CS latches the complete command. If the display is blank, check shutdown mode first, then confirm that the data, clock, and load pins match the library constructor.

Treat the display library as an adapter, not as magic. A library such as LedControl hides the bit shifting and latch timing, but the review still needs to name the processor-side pins, the number of chained devices, the matrix orientation, and the character table used by the application. A character library is usually just a set of eight-byte patterns: each byte represents one row or column of an 8x8 glyph. That makes the first message display a useful integration test because it proves both the wiring and the glyph orientation.

const byte smile[8] = {
  B00111100,
  B01000010,
  B10100101,
  B10000001,
  B10100101,
  B10011001,
  B01000010,
  B00111100
};

void drawGlyph(int device, const byte glyph[8]) {
  for (int row = 0; row < 8; row++) {
    matrix.setRow(device, row, glyph[row]);
  }
}

When several LED blocks are chained, DOUT from one driver feeds DIN on the next and the constructor’s device count changes. That is the main code difference between a one-block demo and a multi-block message board. Keep the physical order explicit: device 0 might be the block nearest the microcontroller or the farthest block, depending on how the modules are wired. A scrolling message, a dice face, or a small game animation should be treated as a final demo after the evidence path has already proved power, orientation, scan limit, intensity, and per-block addressing.

Keep the evidence close to the hardware. Record supply voltage, common ground, library version, DIN/CLK/CS pins, matrix orientation, current setting, and the known-good test pattern. If the first display appears scrambled, fix the row/column mapping or module orientation before adding animations; otherwise the software may hide a wiring error behind a pretty pattern.

Motor MaxCheckpoint: Pixel Chains and Matrices

You now know:

  • WS2812B pixels trade GPIO count for power and timing discipline: full white is about 60 mA per pixel.
  • A 30-pixel full-white case reaches 1.8 A, so the data pin is not the power path.
  • Matrix drivers such as MAX7219/MAX7221 prove orientation, scan limit, intensity, and row data before animations hide wiring mistakes.

Once the output needs words, values, or menus instead of colored states, a display becomes the clearer actuator.

10.5 LCD Displays

10.5.1 16x2 LCD with I2C

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);  // Address 0x27, 16 columns, 2 rows

void setup() {
  lcd.init();
  lcd.backlight();

  lcd.setCursor(0, 0);
  lcd.print("IoT System");
  lcd.setCursor(0, 1);
  lcd.print("Initializing...");

  delay(2000);
}

void loop() {
  // Display temperature
  float temperature = 25.4;

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temperature:");
  lcd.setCursor(0, 1);
  lcd.print(temperature);
  lcd.print(" C");

  delay(2000);

  // Display humidity
  float humidity = 65.2;

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Humidity:");
  lcd.setCursor(0, 1);
  lcd.print(humidity);
  lcd.print(" %");

  delay(2000);
}
Try It: LCD Character Layout Planner

10.6 OLED Displays

OLED displays offer high contrast, low power consumption, and graphical capabilities.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display(128, 64, &Wire, -1);

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setTextColor(SSD1306_WHITE);
}

void loop() {
  // Display sensor readings
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(0, 0);
  display.print("IoT Data");

  display.setTextSize(1);
  display.setCursor(0, 20);
  display.print("Temp: 25.4 C");
  display.setCursor(0, 35);
  display.print("Humid: 65.2 %");
  display.display();
  delay(2000);

  // Draw a progress bar
  for (int pct = 0; pct <= 100; pct += 2) {
    display.clearDisplay();
    display.setCursor(0, 10);
    display.print("Loading...");
    display.drawRect(10, 30, 108, 10, SSD1306_WHITE);
    display.fillRect(12, 32, pct, 6, SSD1306_WHITE);
    display.display();
    delay(40);
  }
}
Try It: OLED Display Memory and Power Estimator
Motor MaxCheckpoint: Displays

You now know:

  • Character LCDs are layout-constrained: a 16x2 display only gives 16 columns per row before text is truncated.
  • OLED choices involve resolution, frame-buffer bytes, lit-pixel current, and interface speed.
  • A display is information-dense, but it only helps when someone is close enough and looking at it.

Visual feedback can show state quietly. The next section covers the output that interrupts attention.

10.7 Buzzers and Tone Generation

10.7.1 Passive Buzzer (Tone Generation)

Passive buzzers can play different frequencies/tones.

Calculate frequencies for musical notes and explore the relationship between pitch and frequency:

Common Notes for Buzzers:

  • C4 (Middle C): 262 Hz
  • A4 (Concert Pitch): 440 Hz
  • C5 (High C): 523 Hz
  • Alert tones typically use 1000-3000 Hz for maximum audibility
#define BUZZER_PIN 25

// Musical notes (frequencies in Hz)
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523

void setup() {
  pinMode(BUZZER_PIN, OUTPUT);
}

void loop() {
  playMelody();
  delay(2000);

  playAlarm();
  delay(2000);

  playNotification();
  delay(5000);
}

void playMelody() {
  int melody[] = {NOTE_C4, NOTE_E4, NOTE_G4, NOTE_C5};
  int durations[] = {250, 250, 250, 500};

  for (int i = 0; i < 4; i++) {
    tone(BUZZER_PIN, melody[i], durations[i]);
    delay(durations[i] * 1.3);  // Pause between notes
  }

  noTone(BUZZER_PIN);
}

void playAlarm() {
  for (int i = 0; i < 5; i++) {
    tone(BUZZER_PIN, 1000, 200);
    delay(250);
    tone(BUZZER_PIN, 500, 200);
    delay(250);
  }

  noTone(BUZZER_PIN);
}

void playNotification() {
  tone(BUZZER_PIN, NOTE_A4, 100);
  delay(150);
  tone(BUZZER_PIN, NOTE_C5, 200);
  delay(250);
  noTone(BUZZER_PIN);
}

10.7.2 Active Buzzer (Simple On/Off)

Active buzzers have built-in oscillators - just supply power.

#define BUZZER_PIN 25

void setup() {
  pinMode(BUZZER_PIN, OUTPUT);
}

void beep(int count, int onTime, int offTime) {
  for (int i = 0; i < count; i++) {
    digitalWrite(BUZZER_PIN, HIGH);
    delay(onTime);
    digitalWrite(BUZZER_PIN, LOW);
    delay(offTime);
  }
}

void loop() {
  // Single beep
  beep(1, 100, 0);
  delay(2000);

  // Double beep
  beep(2, 100, 100);
  delay(2000);

  // Alarm pattern
  beep(5, 50, 50);
  delay(2000);
}
Try It: Buzzer Alert Pattern Designer

Buzzers add urgency, but they also add fatigue. The selection guide that follows treats sound as one channel in a larger feedback design, not as the default answer for every event.

10.8 Display Selection Guide

Display Power Contrast Update Rate Best Use Case
16x2 LCD 20-100mA Medium Fast Indoor, mains powered
OLED 10-50mA High Fast Battery, frequent updates
E-paper 0.001mA Highest Slow (1s) Battery, infrequent updates
TFT LCD 100-300mA Medium Very fast Mains powered, graphics
Bedside Feedback Actuators

Scenario: A team is designing bedside monitors for a clinical ward. Each monitor tracks several patient readings and must draw staff attention to urgent conditions while avoiding constant, low-value beeping.

Constraints:

Requirement Specification Why
Critical alarm response Immediate local awareness Urgent states should not depend on someone watching the display
Ambient noise level Variable, with conversation and equipment noise Audio must be noticeable without being constant
Night shift visibility Low-light conditions Visual cues essential
False alarm handling Suppress nuisance alerts and escalate confirmed problems Prevents alarm fatigue
Power budget Mains-powered (not a constraint) Hospital monitors plugged in

Actuator Selection Analysis:

Feedback Channel Component Selected Rationale
Critical alarm (audio) Passive buzzer or speaker with distinct tone patterns Variable frequency can distinguish alarm classes
Critical alarm (visual) Red strobe or high-visibility LED pattern Visible when staff are not looking at the screen
Warning (audio) Shorter, quieter pulse pattern Distinct from critical alarms and less fatiguing
Warning (visual) Amber LED steady glow Visible but non-urgent; amber = caution
Normal status Green LED steady “All OK” at a glance; no audio (reduces noise floor)
Detailed readings OLED or LCD display sized for the enclosure High contrast and readable labels for local inspection
Nurse station Larger graphical display Multiple patients and alert states can be compared quickly

Why NOT these alternatives?

  • Active buzzer for all alarms: It is simple, but its fixed pitch makes it poor when different alarm classes need different sounds.
  • E-paper display at bedside: It is excellent for rare updates, but its slow refresh is a poor match for frequently changing waveforms.
  • Room-scale colored lighting: It can help in some spaces, but it requires building-level integration. A local high-visibility LED or strobe is simpler to verify.

Design Decision: Audio Pattern Differentiation

The system uses distinct alarm patterns so staff can identify urgency without first reading the screen:

Alarm Type Audio Pattern Frequency Priority
Critical physiological alarm Repeating high-priority pattern High pitch band Highest
Urgent measurement alarm Descending or alternating pattern Mid/high pitch band High
Device or sensor problem Short repeated pulses Mid pitch band Medium
Low battery / sensor off Occasional single pulse Lower pitch band Low

Resulting design: Critical alarms use both a visual channel and an audio channel, warnings use lower-intensity patterns, and normal operation stays visual-only. That separation keeps urgent states noticeable while reducing unnecessary sound.

Motor MaxCheckpoint: Alert Selection

You now know:

  • Passive buzzers need an audio-frequency waveform; active buzzers make their own fixed tone when powered.
  • Alert tones usually target 1000-3000 Hz, while lower tones around 500 Hz can be useful where hearing protection changes perception.
  • Critical states should use more than one channel when people may not be watching the device or may not hear it reliably.

10.9 Knowledge Check

Key Takeaway

Visual and audio actuators provide essential user feedback in IoT systems. LEDs range from simple indicators to addressable strips capable of complex animations. Displays should be selected based on power budget (e-paper for battery, OLED for moderate updates, TFT for rich graphics). Passive buzzers offer flexible tone generation for alerts and melodies, while active buzzers provide simple on/off beeping. Always consider power consumption, as displays and LED strips can be the largest power consumers in a battery-powered IoT device.

“Time for the Output Show!” announced Lila the LED, glowing all the colors of the rainbow. “We’re the actuators that you can SEE and HEAR!”

“Let me go first!” Lila said excitedly. She started dim, then slowly grew brighter and brighter. “Max controls my brightness with PWM – the same trick he uses for motors! But instead of spinning faster, I glow brighter!”

Then a whole strip of her NeoPixel friends lit up, each one a different color. “Meet my addressable friends! Even though there are 30 of us, Max only needs ONE wire to talk to all of us. The first pixel reads its color instruction, then passes the rest of the message down the chain – like a game of telephone, but it actually works perfectly!”

Next, Buzzy the Buzzer cleared his throat. “BEEP BOOP BEEEEP!” He played a little melody. “I’m a passive buzzer, which means Max can make me play ANY note by changing how fast he vibrates me. Higher frequency = higher pitch! I can even play songs!”

“And I’m the screen!” said OLED Olivia, displaying a smiley face. “I can show Sammy’s temperature readings, draw pictures, and even make progress bars. I use tiny organic light-emitting dots – each pixel makes its own light, so I’m super bright and clear!”

“We all work together,” said Sammy the Sensor. “I measure the temperature, Max decides what to do, and then Lila shows green for ‘all good,’ Olivia displays the number, and Buzzy beeps if it gets too hot. Input to output – that’s the IoT loop!”

Bella the Battery whispered, “Just remember, all those pretty lights use MY energy. Turn them off when nobody’s looking!”

10.10 Knowledge Check

Quiz: Visual and Audio Actuators
Match: Visual and Audio Actuator Concepts

Order: Steps to Control LED Brightness with PWM on ESP32

🏷️ Label the Diagram

Code Challenge

10.11 Deep Dive: Feedback Loads, Perception, and Timed LEDs

Status indicator LED panel with power, Wi-Fi, data, sensor, error, and battery indicators beside a GPIO, resistor, LED, and ground return circuit.
Figure 10.1: Status indicator LED array with a current-limited GPIO LED circuit

LEDs, displays, and buzzers are simple only at the user interface. Electrically, each one still has a load path and a control signal. A small status LED shows the pattern: if a 3.3 V GPIO drives a red LED with about 2.0 V forward drop at 10 mA, the resistor must drop 1.3 V, so R = (3.3 - 2.0) / 0.010 = 130 ohms. Choosing 150 ohms gives I = 1.3 / 150 = 0.0087 A, or 8.7 mA. The resistor dissipates 1.3 V x 0.0087 A = 0.011 W, so a small signal resistor has margin. At 25% PWM duty cycle, the average LED current is about 8.7 mA x 0.25 = 2.2 mA.

The design decision is not only electrical. Feedback actuators differ in noticeability, power, and information density. A single green LED is excellent for a healthy status, but poor for a fault that must be noticed across a room. A display can show numbers and labels, but only helps when someone is looking at it. A buzzer interrupts attention, but repeated audio becomes annoying and may be masked by the environment. Strong products combine channels: quiet visual status for normal operation, stronger visual patterns for warnings, and audio only when the state needs immediate attention.

Displays need the same budget discipline. If a small OLED draws 20 mA from a 3.3 V rail while lit, the display load is 3.3 V x 0.020 A = 0.066 W. Left on for 24 hours, that is 0.066 W x 24 h = 1.58 Wh before regulator losses. On a small battery device, that can dominate the energy budget. If the value changes only occasionally, e-paper is often a better human interface because it can keep an image visible between refreshes without continuous display power.

Buzzers split into two kinds that are often confused. An active buzzer has an internal oscillator and produces one fixed tone when powered. A passive piezo or magnetic buzzer needs the controller to supply an audio-frequency waveform. A 2 kHz passive-buzzer alert has a period of 1 / 2000 = 0.0005 s, or 500 microseconds; a 50% square wave is high for about 250 microseconds and low for about 250 microseconds. A lower 500 Hz warning tone has a period of 1 / 500 = 0.002 s, or 2 ms. The controller changes pitch by changing the period, not by changing the supply voltage.

Addressable LEDs such as WS2812/NeoPixel parts add a different kind of timing constraint. Each pixel contains a driver chip, reads the first 24 bits as its green, red, and blue values, and forwards the rest downstream. There is no clock line; each bit is encoded by pulse width and lasts roughly 1.25 microseconds. A 30-pixel strip therefore needs 30 pixels x 24 bits = 720 bits, or 720 x 1.25 = 900 microseconds, plus the reset interval. An interrupt that pauses the GPIO waveform halfway through a bit can corrupt the data seen by every later pixel.

That timing issue is separate from the power issue. The same 30-pixel strip at full white can draw 30 x 60 mA = 1.8 A, which is 5 V x 1.8 A = 9 W. A microcontroller pin can generate the data waveform, but the 5 V supply and ground return must carry the power. Random flicker can come from data timing or from supply droop, so debug in order: limit brightness, confirm common ground, check the 5 V rail under load, then inspect whether the data driver can keep sub-microsecond timing without interruption.

10.12 Summary

Visual and audio actuators transform digital data into human-perceivable feedback. Key concepts:

LED Control:

  • PWM dimming varies duty cycle (not voltage) to control perceived brightness
  • 8-bit PWM provides 256 brightness levels (0-255)
  • Power consumption scales linearly with duty cycle
  • RGB LEDs require three independent PWM channels

Addressable LED Strips:

  • WS2812B (NeoPixel) LEDs contain integrated driver chips
  • Single data wire controls hundreds of individually addressable pixels
  • Full white draws ~60mA per LED; single colors ~20mA
  • High current draws require external power supplies (not USB)

Displays:

  • LCD (16x2): Simple text, 20-100mA, ideal for mains-powered devices
  • OLED: High contrast, 10-50mA, battery-friendly with frequent updates
  • E-paper: Ultra-low power (0.001mA standby), slow refresh, best for infrequent updates
  • TFT LCD: Rich graphics, 100-300mA, requires mains power

Buzzers:

  • Passive: Requires frequency input, can play any tone/melody
  • Active: Built-in oscillator, simple ON/OFF control, fixed frequency
  • Alert tones: 1000-3000 Hz for maximum audibility
  • Low frequencies (~500 Hz) penetrate hearing protection better

Design Considerations:

  • Power budget is critical for battery-powered devices
  • Multi-modal feedback (visual + audio) improves critical alert perception
  • Distinct patterns prevent alarm fatigue in safety-critical applications
  • Standard resistor values (E12/E24 series) for current limiting

Common Pitfalls

An LED connected directly from VCC to GPIO (or directly to a supply) has no resistance to limit current. LED forward voltage (1.8-3.5 V) is much less than supply voltage (3.3-5 V). The excess voltage forces very high current through the LED, burning it out within seconds. Always calculate and install a current limiting resistor: R = (Vsupply - Vf) / If_desired.

A passive buzzer requires an oscillating signal (PWM at audio frequency) to produce sound — it is simply a piezo element that vibrates at the applied frequency. Applying a DC HIGH from a GPIO pin to a passive buzzer produces no sound (or a brief click as it deflects). Use analogWrite() or tone() with an audio-range frequency (1 kHz - 5 kHz) for audible output from passive buzzers.

WS2812B addressable LED strips draw up to 60 mA per RGB LED at full white brightness. A strip of 30 LEDs draws 1.8 A. This exceeds GPIO current limits by 100x and exceeds typical USB power adapter capacity. Always power LED strips from a dedicated 5 V power supply rated for the full strip current, with a shared common ground to the MCU.

Active buzzers contain an internal oscillator and produce a fixed tone when voltage is applied (just connect VCC and GND). Passive buzzers require an external oscillating signal. They look identical externally and share the same package styles. Testing with a DC supply: active buzzers beep immediately; passive buzzers are silent. Apply the wrong driving method to the wrong buzzer type and you will get no sound.

10.13 What’s Next?

Now that you understand visual and audio actuators, explore related actuator types and deeper control techniques.

Next Topic Description
PWM Control Deeper dive into duty cycle calculations and waveform generation
DC Motors Speed and direction control using H-bridge drivers and PWM
Servo Motors Precise angular positioning with pulse-width control
Actuator Safety Flyback protection, current limiting, and thermal management
Actuator Classifications Survey of all actuator types and selection criteria