Overview
This week completed the sensor board by implementing and testing the output devices - an LED and a speaker. After successfully reading sensor data in Week 8, the assignment now required adding output devices to provide feedback based on those measurements. The goal was to create a complete interactive system where environmental inputs (light and temperature) control visible and audible outputs, creating an ambient environmental feedback device.
Understanding the Output Devices
LED: Visual Feedback
LEDs (Light Emitting Diodes) are semiconductor devices that emit light when current flows through them. Unlike incandescent bulbs that generate light from heat, LEDs produce light through electroluminescence - when electrons recombine with holes in the semiconductor material, they release energy as photons. This makes LEDs extremely efficient, with most energy converted to light rather than wasted as heat.
The forward voltage drop of an LED varies by color - typically around 2V for red, 3V for green and blue. Since the XIAO ESP32-C3 operates at 3.3V and its GPIO pins can't source much current (typically 20-40mA max), I used a current-limiting resistor to protect both the LED and the microcontroller. A 330Ω resistor limits current to approximately 10mA, providing good brightness while staying well within safe operating limits.
Speaker: Audio Feedback
The speaker in my design is a small piezoelectric or electromagnetic transducer that converts electrical signals into sound waves. Unlike high-fidelity speakers that require complex amplification, this simple speaker can be driven directly from a microcontroller GPIO pin through a transistor driver circuit. The transistor acts as a switch, allowing the small GPIO output to control larger currents needed to drive the speaker coil.
The ESP32-C3's hardware PWM capabilities enable tone generation. By rapidly toggling the GPIO pin at audio frequencies (typically 20Hz to 20kHz), the speaker membrane vibrates at that frequency, producing sound. The `tone()` function in Arduino simplifies this by automatically configuring the PWM hardware to generate square waves at specified frequencies.
Assembly Challenges
Soldering challenges - excessive heat caused some copper traces to lift
During assembly, I encountered some soldering difficulties. The reflow process with solder paste required careful heat management, and in some areas, excessive temperature caused copper traces to lift slightly from the FR4 substrate. This is a common issue with PCB milling - the copper adhesion can be weaker than with commercially manufactured boards, making it more susceptible to delamination under heat stress.
A speaker was broken due to the excessive heat, the vibration film was damaged
The speaker connection presented particular challenges. The physical stress from the speaker wires, combined with the heat from soldering, created a weak joint that was prone to breaking. After the initial assembly failed, I had to carefully re-solder the speaker connections, adding more solder for mechanical strength and using strain relief techniques to prevent the wires from pulling on the joints.
Final assembled PCB with all components functional
After addressing these assembly issues, the board was complete and functional. All components - the XIAO ESP32-C3, sensors, LED, speaker, and supporting resistors and capacitors - were properly connected and ready for programming. The assembly challenges taught valuable lessons about soldering technique, thermal management, and the importance of mechanical robustness in electronic assemblies.
LED Output Implementation
LED responding to light sensor input - turns on in dark conditions
Simple On/Off Control
The LED implementation uses straightforward digital output control. Based on the light sensor reading, the LED turns on when ambient light falls below a threshold, effectively creating an automatic night light. This demonstrates the basic principle of sensor-actuator systems - environmental conditions trigger specific output responses.
// LED behavior: ON when dark
if (lux < 50) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
This simple threshold-based control is surprisingly effective. The 50 lux threshold was chosen empirically - it's dark enough to indicate actual low-light conditions but not so high that it triggers in typical indoor lighting. The immediate response provides clear visual feedback about the light sensing system's operation.
Potential Enhancements
While the current implementation uses simple on/off control, the LED could be enhanced with PWM dimming to create graduated responses. For example, the LED brightness could inversely track ambient light - getting brighter as it gets darker. This would require using `analogWrite()` to control LED brightness through PWM, creating a more sophisticated ambient lighting response.
Speaker Output Implementation
Audio Pattern Generation
The speaker implementation is more sophisticated than the LED, using both frequency (pitch) and timing (rhythm) to convey information about the environment. The sound pattern adapts based on both temperature and light readings, creating an audible representation of the sensor state.
// Helper: play a pattern that depends on temp + light
void playSoundPattern(float celsius, float lux) {
// Choose pitch from temperature
int baseFreq;
if (celsius < 22) {
baseFreq = 300; // cold: low tone
} else if (celsius < 28) {
baseFreq = 700; // comfy: mid tone
} else {
baseFreq = 1300; // hot: high tone
}
// Choose rhythm from light
if (lux < 50) {
// Dark: one long beep, slow
tone(SPEAKER_PIN, baseFreq, 400);
delay(600);
} else if (lux < 300) {
// Medium light: two medium beeps
for (int i = 0; i < 2; i++) {
tone(SPEAKER_PIN, baseFreq, 220);
delay(280);
}
delay(300);
} else {
// Bright: three quick beeps
for (int i = 0; i < 3; i++) {
tone(SPEAKER_PIN, baseFreq, 120);
delay(150);
}
}
}
Multi-Parameter Encoding
This audio feedback system cleverly encodes two environmental parameters into different aspects of sound. Temperature controls pitch - cold environments produce low tones (300Hz), comfortable temperatures create mid-range tones (700Hz), and warm conditions generate high-pitched tones (1300Hz). This frequency range is well within human hearing and the frequencies are distinct enough to be easily differentiated.
Light level controls the rhythm pattern. Dark conditions produce a single long beep with a slow repetition rate, medium lighting creates two medium beeps, and bright conditions trigger three quick beeps. This combination of pitch and rhythm allows a person to understand both environmental parameters just by listening, without looking at any display.
PWM Audio Generation
The `tone()` function generates square wave audio using hardware PWM. The ESP32-C3 has multiple PWM channels that can generate precise frequencies. The function takes three parameters: the pin number, frequency in Hertz, and optional duration in milliseconds. When duration is specified, the tone plays for that time and then stops automatically, simplifying the timing code.
Power Consumption Measurement
Speaker Power Analysis
I measured the speaker's power consumption to understand the system's energy requirements. Using a multimeter in series with the speaker circuit, I found that the speaker draws approximately 16mA when actively playing tones. This measurement was taken during typical operation with the tone generation patterns described above.
| Component | Current Draw | Conditions | Power @ 3.3V |
|---|---|---|---|
| XIAO ESP32-C3 | ~60-80mA | Active operation | ~200-260mW |
| Speaker (active) | 16mA | Playing tones | ~53mW |
| LED (on) | ~10mA | Full brightness | ~33mW |
| Sensors (passive) | <1mA | Continuous sensing | <3mW |
| Total (all active) | ~86-106mA | Worst case | ~283-350mW |
The speaker's 16mA draw is relatively modest compared to the microcontroller's base consumption. The transistor driver circuit efficiently switches the speaker current, minimizing losses. Most of the power is actually dissipated in the speaker coil as it converts electrical energy to mechanical motion (sound waves). At 16mA, the speaker is within the safe operating range for continuous operation without overheating.
For battery-powered applications, these measurements inform design decisions. The total system draw of ~100mA means a 1000mAh battery could theoretically run the system for about 10 hours, though practical runtime would be less due to battery discharge curves and efficiency losses. Power optimization could include reducing microcontroller clock speed, using sleep modes between measurements, or dimming the LED.
Complete System Integration
Sensor-to-Actuator Pipeline
The complete system creates a closed loop from sensing to action. The phototransistor and thermistor continuously monitor the environment, converting light and temperature into electrical signals. The ESP32-C3's ADC digitizes these signals, and the firmware processes them into meaningful measurements. Based on these measurements, the code makes decisions about output states - should the LED be on? What pitch and rhythm should the speaker play?
This sensing-processing-actuating loop runs continuously in the main program loop, cycling every 600-800 milliseconds (depending on the speaker pattern). The delay between cycles prevents the speaker from being overwhelming while still providing regular environmental feedback. This creates an ambient awareness system that subtly communicates environmental state through light and sound.
Output Demonstration
Key Learnings
Output Device Electronics
Implementing output devices reinforced important electronics principles. LEDs require current limiting to prevent damage - the forward voltage drop and maximum current rating must be respected. Speakers and other inductive loads benefit from transistor drivers because microcontroller GPIO pins have limited current capacity and can be damaged by inductive kickback. Understanding these constraints is essential for reliable output device control.
Soldering and Assembly Quality
The assembly challenges highlighted the importance of good soldering technique and mechanical design. Heat management during soldering prevents copper delamination, adequate solder provides mechanical strength, and strain relief prevents broken joints from physical stress. These lessons about manufacturability apply whether making prototypes or designing production systems - good mechanical design is as important as correct electrical design.
Power Budgeting
Measuring power consumption revealed where energy goes in an embedded system. The microcontroller dominates power draw, while peripherals like LEDs and speakers add incremental loads. For battery-powered or energy-harvesting applications, this breakdown informs optimization strategies. Sometimes adding a more efficient microcontroller or using sleep modes saves more power than optimizing peripheral usage.
Complete System Code
Here's the complete Arduino code that integrates both input and output devices, creating a functioning environmental feedback system:
#include <math.h>
// ----- NTC Thermistor constants -----
const float BETA = 3950; // should match your thermistor
// ----- Photoresistor constants -----
const float GAMMA = 0.7;
const float RL10 = 50; // resistance at 10 lux (kΩ-ish)
// ----- Pins on XIAO ESP32-C3 -----
const int TEMP_PIN = D1; // analog-capable
const int LIGHT_PIN = D2; // analog-capable
const int LED_PIN = D7; // digital
const int SPEAKER_PIN = D4; // digital (tone)
// Helper: play a pattern that depends on temp + light
void playSoundPattern(float celsius, float lux) {
// ---------- Choose pitch from temperature ----------
int baseFreq;
if (celsius < 22) {
baseFreq = 300; // cold: low tone
} else if (celsius < 28) {
baseFreq = 700; // comfy: mid tone
} else {
baseFreq = 1300; // hot: high tone
}
// ---------- Choose rhythm from light ----------
if (lux < 50) {
// Dark: one long beep, slow
tone(SPEAKER_PIN, baseFreq, 400);
delay(600);
} else if (lux < 300) {
// Medium light: two medium beeps
for (int i = 0; i < 2; i++) {
tone(SPEAKER_PIN, baseFreq, 220);
delay(280);
}
delay(300);
} else {
// Bright: three quick beeps
for (int i = 0; i < 3; i++) {
tone(SPEAKER_PIN, baseFreq, 120);
delay(150);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
Serial.println();
Serial.println("XIAO ESP32-C3 - Temp + Light Audio Demo");
}
void loop() {
// ----------------------------------
// 1) Read temperature from NTC (TEMP_PIN)
// ----------------------------------
int ntcValue = analogRead(TEMP_PIN); // ESP32-C3: 0–4095
// Adapted your formula for 12-bit ADC (4095) and 3.3V
float celsius = 1.0 / (log(1.0 / (4095.0 / ntcValue - 1.0)) / BETA + 1.0 / 298.15) - 273.15;
Serial.print("Temperature: ");
Serial.print(celsius);
Serial.println(" °C");
// ----------------------------------
// 2) Read light from photoresistor (LIGHT_PIN)
// ----------------------------------
int lightValue = analogRead(LIGHT_PIN); // 0–4095
// Convert to voltage using 3.3V reference on ESP32-C3
float voltage = lightValue * 3.3 / 4095.0;
// Assuming 2k series resistor to 3.3V
float resistance = 2000.0 * voltage / (3.3 - voltage);
float lux = pow(RL10 * 1000.0 * pow(10, GAMMA) / resistance, (1.0 / GAMMA));
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lux");
// ----------------------------------
// 3) LED behavior: ON when dark
// ----------------------------------
if (lux < 50) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
// ----------------------------------
// 4) Play sound pattern that strongly reflects sensors
// ----------------------------------
playSoundPattern(celsius, lux);
Serial.println("------------------------");
}
This code demonstrates the complete embedded systems development cycle: reading analog sensors, processing signals into meaningful units, making control decisions based on sensor data, and driving output devices to provide feedback. The combination of inputs and outputs creates an interactive system that responds to its environment in real-time.
Future Enhancements
Several improvements could enhance this environmental feedback system. PWM control of the LED could provide graduated brightness responses rather than simple on/off. More sophisticated audio patterns could encode additional information or use different waveforms for better speaker efficiency. Adding wireless connectivity through the ESP32-C3's WiFi could enable data logging, remote monitoring, or integration with home automation systems.
The sensor-actuator pairing could also be made more sophisticated with hysteresis (different thresholds for turning on vs off) to prevent rapid switching near threshold values. Adaptive thresholds that adjust based on historical data could make the system context-aware. And adding more output devices - like RGB LEDs for color-coded feedback or a small display for numerical readings - could create richer user interactions.