Output Devices
Here is the link to our group assignment:
Week 10 Group Assignment — Output Devices.
This week covers output devices: how actuators and displays draw power, and how to control them from a microcontroller. Below I reflect on the group power-measurement exercise and document my individual WS2812B LED project on the Week 8 board.
Group Assignment — Measuring Output Power
The group task was to measure the power consumption of an output device and document it on the group page. We used the relationship P = V × I (power in watts = voltage × current).
How we measured: we broke the positive supply line and placed a multimeter in current (A) mode in series, so all load current flows through the meter. We measured the supply voltage at the same time (typically ~5 V from USB or a bench supply). Multiplying V and I gives power in watts (or mW for small loads).
Our group tested several output devices (for example LEDs, servos, and addressable LED strips). For an addressable strip like the WS2812B, current is not fixed — it depends on how many pixels are on and which colour. Rough guide from our measurements and datasheets:
- All pixels off: only a few mA (strip idle logic)
- One pixel lit (moderate brightness): tens of mA
- 10 pixels white at higher brightness: can reach ~100–200 mA or more
- Full strip blinking: average current sits between “all on” and “all off” depending on duty cycle
What I learned from the group work: always size the power supply for the worst case (all outputs active at max brightness), not for idle current. Thin USB cables and weak 5 V regulators can sag under load, which makes WS2812B pixels brownish or unreliable. Measuring in series is awkward but gives trustworthy numbers; a USB inline power meter is faster for quick checks. Full tables and photos are on the group assignment page.
Individual Assignment — WS2812B LED Strip
For the individual assignment I added an output device to the microcontroller board I designed and milled in
Week 8 (SEEED XIAO ESP32-C3 + tactile button on D0). The output is a WS2812B addressable LED module with 10 pixels in one chain.
Hardware:
- MCU: XIAO ESP32-C3 on my Week 8 PCB (USB power)
- Input: tactile button on D0 (same debounced press detection idea as Week 8 / Week 9)
- Output: WS2812B data line on D3; 5 V and GND to the LED module; 10 LEDs daisy-chained
WS2812B pixels receive 24-bit colour data on a single wire. The ESP32 sends a precise timing pattern; each LED regenerates the stream for the next pixel in the chain. I used the Adafruit NeoPixel library (WS2812 / NEO_GRB + 800 kHz).
Behaviour I programmed:
- At start, all 10 LEDs are off.
- Each button press (debounced) lights one more LED in blue (press 1 → 1 LED, press 2 → 2 LEDs, …).
- On the 10th press, all 10 LEDs turn on, then blink together for 5 seconds.
- After blinking, all LEDs turn off and the press counter resets to zero — ready to start again.
During the celebration phase the firmware skips button reads so bounce on the switch cannot restart the sequence mid-blink. Serial Monitor at 115200 baud prints the press count for debugging.
Source file:
ws2812_button.ino
(install Adafruit NeoPixel from the Arduino Library Manager).
Code
Main logic: debounced button → increment counter → update pixels → celebration blink → reset.
#include
#define PIN_NEO D3
#define PIN_BTN D0
#define NUMPIXELS 10
Adafruit_NeoPixel pixels(NUMPIXELS, PIN_NEO, NEO_GRB + NEO_KHZ800);
const unsigned long DEBOUNCE_MS = 50;
const unsigned long CELEBRATE_MS = 5000;
const unsigned long BLINK_MS = 250;
int pressCount = 0;
int buttonState = LOW;
int lastReading = LOW;
unsigned long lastDebounceTime = 0;
bool celebrating = false;
unsigned long celebrateStart = 0;
void showProgress(int count) {
pixels.clear();
for (int i = 0; i < count; i++) {
pixels.setPixelColor(i, pixels.Color(0, 80, 255)); // blue
}
pixels.show();
}
void startCelebration() {
celebrating = true;
celebrateStart = millis();
}
void setup() {
pinMode(PIN_BTN, INPUT);
pixels.begin();
pixels.setBrightness(80);
pixels.clear();
pixels.show();
Serial.begin(115200);
Serial.println(F("WS2812B button demo: press to light LEDs one by one."));
}
void loop() {
if (celebrating) {
unsigned long elapsed = millis() - celebrateStart;
if (elapsed >= CELEBRATE_MS) {
celebrating = false;
pressCount = 0;
pixels.clear();
pixels.show();
Serial.println(F("Reset — all LEDs off."));
return;
}
if (((elapsed / BLINK_MS) % 2) == 0) {
for (int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(255, 255, 255));
}
} else {
pixels.clear();
}
pixels.show();
return;
}
int reading = digitalRead(PIN_BTN);
if (reading != lastReading) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > DEBOUNCE_MS) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
pressCount++;
Serial.print(F("Press #"));
Serial.println(pressCount);
if (pressCount >= NUMPIXELS) {
showProgress(NUMPIXELS);
startCelebration();
} else {
showProgress(pressCount);
}
}
}
}
lastReading = reading;
}
Here is the video of the output device:
What I Learned
Output vs input: last week I read a button as input; this week the MCU drives an load. The WS2812B is timing-sensitive — long interrupts or heavy Wi-Fi tasks can glitch the colour stream, so keep the loop simple during pixels.show().
Power: group measurements matched what I saw on the bench — lighting more pixels or blinking white pulls noticeably more current than a single blue LED. That matters for USB-powered boards like mine.
Integration: reusing the Week 8 PCB meant I already had a proven button net (D0) and a free GPIO (D1) for NeoPixel data. Combining Week 9 debouncing with Week 10 output control felt like a small but complete embedded system.
Software state machine: separating “normal counting” from “celebration blink” in loop() avoided edge-case bugs (double triggers, stuck all-on). A explicit reset after 5 s makes the demo repeatable for instructors without power-cycling.