Week 10: Output Devices¶
Week 10 Assignment:
-
Group Assignment
- Measure the power consumption of an output device
-
Individual Assignment
- Add an output device to a microcontroller board you’ve designed, and program it to do something
GROUP ASSIGNMENT¶
I measured the power consumption of an LED from this circuit using different resistors.
Power can be calculated using the following equation:
Power (W) = Voltage (V) × Current (I)
Ohm’s Law:
Voltage (V) = Current (I) × Resistance (R)
-
Experiment 1: Using a 218 Ω Resistor
-
Step 1: Measuring Resistance
I measured the resistance of the first resistor: 218 Ω

-
Step 2: Measuring Voltage (LED & Resistor)
Using a multimeter:
-
The voltage across the LED + resistor is 2.99 V

-
The voltage across the LED only is 1.87 V

-
Therefore, the voltage across the resistor only is: 2.99 V − 1.87 V = 1.12 V
-
-
Step 3: Measuring Current
Calculated Current: Since I know the voltage across the resistor (1.12 V) and its resistance (218 Ω), I used Ohm’s Law (I = V / R) to calculate the current:
I = 1.12 V / 218 Ω = 5.14 mAMeasured Current: I also measured the current using a multimeter: 4.86 mA

The Difference
-> The calculated current (5.14 mA) and measured current (4.86 mA) are close. The difference may be due to measurement error or component tolerances.
-
Step 4: Calculating Power
I calculated the power consumption of the LED based on the measured values:
P = 1.87 V × 4.86 mA = 0.009 W = 9.1 mW
-
-
Experiment 2: Using a 100 Ω Resistor
-
Step 1: Measuring Resistance
I measured the resistance of the first resistor: 100 Ω

-
Step 2: Measuring Voltage (LED & Resistor)
Using a multimeter:
-
The voltage across the LED + resistor is 2.99 V

-
The voltage across the LED only is 1.87 V

-
Therefore, the voltage across the resistor only is: 2.99 V − 1.87 V = 1.12 V
-
-
Step 3: Measuring Current
Calculated Current: Since I know the voltage across the resistor (1.12 V) and its resistance (218 Ω), I used Ohm’s Law (I = V / R) to calculate the current:
I = 1.12 V / 100 Ω = 11.2 mAMeasured Current: I also measured the current using a multimeter: 7.66 mA

-
Step 4: Calculating Power
I calculated the power consumption of the LED based on the measured values:
P = 1.87 V × 7.66 mA = 0.014 W = 14.32 mW
-
-
Experiment 3: Using a 328 Ω Resistor
-
Step 1: Measuring Resistance
I measured the resistance of the first resistor: 328 Ω

-
Step 2: Measuring Voltage (LED & Resistor)
Using a multimeter:
-
The voltage across the LED + resistor is 2.99 V

-
The voltage across the LED only is 1.87 V

-
Therefore, the voltage across the resistor only is: 2.99 V − 1.87 V = 1.12 V
-
-
Step 3: Measuring Current
Calculated Current: Since I know the voltage across the resistor (1.12 V) and its resistance (218 Ω), I used Ohm’s Law (I = V / R) to calculate the current:
I = 1.12 V / 328 Ω = 3.41 mAMeasured Current: I also measured the current using a multimeter: 3.49 mA

-
Step 4: Calculating Power
I calculated the power consumption of the LED based on the measured values:
P = 1.87 V × 3.49 mA = 0.0065 W = 6.53 mW
-
Summary
| Resistor Resistance (R) | LED Voltage (V) | Current (I) | Power (V x I) |
|---|---|---|---|
| 100 Ω | 1.87 V | 7.66 mA | 14.32 mW |
| 218 Ω | 1.87 V | 4.86 mA | 9.1 mW |
| 328 Ω | 1.87 V | 3.49 mA | 6.53 mW |
- Higher resistance -> lower current (Ohm’s Law)
- Lower current -> lower power (since P = V x I)
INDIVIDUAL ASSIGNMENT¶
This week, I experimented with different kinds of output devices, including LCD, OLED, Buzzer and LED.
LCD vs OLED
-
LCD (Liquid Crystal Display) -> There are backlight (a big light source in the back) and a layer of liquid crystals in front. The response time is slower, the crystals have to move/rotate to change color.
-
OLED (Organic Light-Emitting Diode) -> Unlike LCD, OLED doesn’t have backlight. Each individual pixel is made of organic material that glows when you give it electricity. The response time is instant: when electricity hits the organic material, it changes light output immediately.
For all the experiments, I used the XIAO ESP32C3 as the microcontroller.

Moreover, I used the Grove Base for XIAO as an expansion board. This board acts as a bridge between the Seeed Studio XIAO and the Grove modules.

LCD RGB Backlight, LCD (White on Blue)¶
-
Prepare the materials needed:
- XIAO ESP32C3
- Grove Base for XIAO
- Grove - LCD RGB Backlight
Grove - LCD RGB Backlight:
It enables the user to set any color preference with a simple and concise Grove interface.
Features:
- RGB Backlight
- I2C communication
- Built-in English and Japanese fonts
- 16x2 LCD
Specifications:
Item Value Input Voltage 3.3/5V Operating Current <60mA CGROM 10880 bit CGRAM 64x8 bit LCD I2C Address 0X3E RGB I2C Address 0X62 
-
Connect Grove-LCD RGB Backlight to I2C port of Grove Base
-
Plug XIAO ESP32C3 to Grove Base
-
Connect XIAO ESP32C3 to PC via a USB-C cable
-
Download the Grove-LCD RGB Backlight Library from Github
-
Open Arduino IDE. Click on
Sketch -> Include Library -> Add .ZIP Library -
Check if the library install correctly. Click on
File -> Examples -> Grove - LCD RGB Backlight -> choose an example, I chose “HelloWorld”.
There are 13 examples in the library:
Autoscroll,Blink,Cursor,CustomCharacter,CustomCharacterProgmem,Display,fade,HelloWorld,Scroll,SerialDisplay,setColor,setCursor,TextDirection -
I uploaded the code, but somehow it didn’t work. It only showed red RGB backlight on the Grove - LCD RGB Backlight.

LCD not working
- Power and RGB backlight chip are working (I2C part at address 0x62)
- The LCD controller (text driver, usually 0x3E) is not communicating properly
I tried to use another LCD: Grove - 16x2 LCD (White on Blue), and it worked well:
Grove - 16x2 LCD (White on Blue):
It enables the user to set any color preference with a simple and concise Grove interface.
Features:
- Display construction: 16 Characters, 2 Lines
- Display mode: STN
- On board MCU
- I2C-bus interface
- Support English and Japanese fonts
Specifications:
Item Value Operating Voltage 3.3V / 5V Operating temperature 0 to 50℃ Storage temperature -10 to 60℃ Driving method 1/16 duty, 1/5 bias Interface I2C I2C Address 0X3E
Buzzer¶
Since I am going to use OLED/LCD and buzzer for my final project, I want to experiment with these output components together. I followed this experiment: Toothbrushing Instructor
-
Prepare the materials needed:
- XIAO ESP32C3
- Grove Base for XIAO
- Grove - Mech Keycad
- Grove - 16x2 LCD (White on Blue)
- Grove - Buzzer
Grove - Buzzer:
This module has a piezo buzzer which can be connected to digital outputs and it will emit a tone when the output is HIGH. It can also be connected to an analog pulse-width modulation output to generate various tones and effects.
Feature:
- Easy to use piezoelectric buzzer
- Uses Standard 4-pin Grove Cables to connect to other Grove modules such as - Grove Power Modules and Grove - Base Shield
- Digital port
Specifications:
Item Value Operating Voltage 3.3V/5V Sound Output ≥85dB Resonant Frequency 2300±300Hz 
-
Connect Grove - 16x2 LCD to port I2C, Grove - Mech Keycad to port D0, and Grove - Buzzer to port D2 of Grove Base
-
Plug XIAO ESP32C3 to Grove Base

-
Connect XIAO ESP32C3 to PC via a USB-C cable
-
Copy the following code into Arduino IDE and upload the code:
This code is generated from ChatGPT
#include <Wire.h> #include "rgb_lcd.h" rgb_lcd lcd; const int buzzerPin = D2; const int buttonPin = D0; // LCD color (blue) const int colorR = 0; const int colorG = 0; const int colorB = 200; void setup() { Wire.begin(); lcd.begin(16, 2); lcd.setRGB(colorR, colorG, colorB); lcd.setCursor(0, 0); lcd.print("TIME 2:00"); lcd.setCursor(0, 1); lcd.print("PRESS BUTTON"); pinMode(buzzerPin, OUTPUT); pinMode(buttonPin, INPUT); } void loop() { if (digitalRead(buttonPin) == HIGH) { delay(200); // simple debounce StartToothBrushTimer(); } delay(100); } void StartToothBrushTimer() { int totalSeconds = 120; for (int i = totalSeconds; i >= 0; i--) { int minute = i / 60; int second = i % 60; lcd.clear(); lcd.setCursor(0, 0); // format time if (second < 10) lcd.print("TIME: " + String(minute) + ":0" + String(second)); else lcd.print("TIME: " + String(minute) + ":" + String(second)); // buzz every 30 sec if (second == 0 || second == 30) { doBuzz(); lcd.setCursor(0, 1); if (i > 90) lcd.print("OUTSIDE TOP"); else if (i > 60) lcd.print("INSIDE TOP"); else if (i > 30) lcd.print("OUTSIDE BOT"); else lcd.print("INSIDE BOT"); } delay(1000); } lcd.clear(); lcd.setCursor(0, 0); lcd.print("TIME 2:00"); lcd.setCursor(0, 1); lcd.print("PRESS BUTTON"); } void doBuzz() { digitalWrite(buzzerPin, HIGH); delay(200); digitalWrite(buzzerPin, LOW); } -
Press the button (Grove – Mech Keycap) and the counter will start. A ‘beep’ sound will come from the buzzer.
OLED, LED, Buzzer¶
These are all the output devices (OLED 0.96”, LED, and Buzzer) I will use for my final projects. So I want to experiment with these materials.
-
Prepare the materials needed:
- XIAO ESP32C3
- OLED 0.96” (I tested the I2C connection of the OLED 0.96” with logic analyzer. I documented it on Week 6 (Logic Analyzer))
- Button 5x
- LED + Resistor
- Grove - Buzzer
- Jumper Wires
- Breadboard (I acknowledge that is not recommended to use the breadboard due to its problem in wiring connections, but the CNC milling is not ready to use yet, and I just want to temporary check the circuit. If everything is already ok, maybe I will order the PCB to PCB design house)
-
I simulate the circuit in Wokwi.
-
Then, I connected all the materials with the XIAO ESP32C3:

-
OLED 0.96”
- GND -> GND
- VCC -> 3.3V
- SCC -> GPIO 7
- SDA -> GPIO 6
-
Button 5x:
- Button A -> GPIO 10
- Button B -> GPIO 9
- Button C -> GPIO 8
- Button D -> GPIO 20
- Button 1 -> GPIO 5
- the other side of the buttons going to GND
-
LED + resistor:
- GPIO 4 -> Resistor -> LED (+)
- LED (-) -> GND
-
Buzzer
- GND -> GND
- VCC -> 5V
- SIG -> GPIO 3
The final set up:

-
-
Connect XIAO ESP32C3 to PC via a USB-C cable
-
Copy the following code into Arduino IDE and upload the code:
This code is generated from ChatGPT
#include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // -------- PIN DEFINITIONS -------- // Buttons #define BTN_A 10 #define BTN_B 9 #define BTN_C 8 #define BTN_D 20 #define BTN_1 5 // Outputs #define LED_PIN 4 #define BUZZER_PIN 3 // -------- LED TIMER -------- unsigned long ledTimer = 0; bool ledOn = false; const int LED_DURATION = 500; // 0.5 seconds // -------- SETUP -------- void setup() { Serial.begin(115200); // I2C init (SDA = 6, SCL = 7) Wire.begin(6, 7); // OLED init if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println("OLED not found"); while (true); } showCentered("AWL READY?"); // Button inputs pinMode(BTN_A, INPUT_PULLUP); pinMode(BTN_B, INPUT_PULLUP); pinMode(BTN_C, INPUT_PULLUP); pinMode(BTN_D, INPUT_PULLUP); pinMode(BTN_1, INPUT_PULLUP); // Outputs pinMode(LED_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); } // -------- MAIN LOOP -------- void loop() { if (pressed(BTN_1)) { showCentered("RAISEHANDS"); beep(); turnOnLED(); delay(200); } if (pressed(BTN_A)) { showCentered("A"); beep(); turnOnLED(); delay(200); } if (pressed(BTN_B)) { showCentered("B"); beep(); turnOnLED(); delay(200); } if (pressed(BTN_C)) { showCentered("C"); beep(); turnOnLED(); delay(200); } if (pressed(BTN_D)) { showCentered("D"); beep(); turnOnLED(); delay(200); } // LED auto OFF after 0.5 seconds if (ledOn && millis() - ledTimer > LED_DURATION) { digitalWrite(LED_PIN, LOW); ledOn = false; } } // -------- FUNCTIONS -------- bool pressed(int pin) { return digitalRead(pin) == LOW; } void turnOnLED() { digitalWrite(LED_PIN, HIGH); ledTimer = millis(); ledOn = true; } // Improved beep using tone void beep() { tone(BUZZER_PIN, 1000); // 1000 Hz sound delay(150); noTone(BUZZER_PIN); } void showCentered(String text) { display.clearDisplay(); display.setTextSize(2); display.setTextColor(WHITE); int16_t x, y; uint16_t w, h; display.getTextBounds(text, 0, 0, &x, &y, &w, &h); int centerX = (SCREEN_WIDTH - w) / 2; int centerY = (SCREEN_HEIGHT - h) / 2; display.setCursor(centerX, centerY); display.print(text); display.display(); } -
First, the OLED will show ‘AWL READY?’
If you press Button 1, the OLED will show ‘RAISEHANDS’.
If you press Button 2, the OLED will show ‘A’.
If you press Button 3, the OLED will show ‘B’.
If you press Button 4, the OLED will show ‘C’.
If you press Button 4, the OLED will show ‘D’.
In every button press, the LED will turn on for 0.5s and the buzzer will sound ‘beep’.