Week 10: Output Devices
Assignments:
Group Assignment
- Measure the power consumption of an output device.
- Document your work to the group work page and reflect on your individual page what you learned
Individual Assignment
- Add an output device to a microcontroller board youβve designed and program it to do something..
Things to Complete This Week
- Explore different output devices
- Document process
- Work on Final Project PCB!!!
Here is my schedule for this week.
Here is the link to my schedule
Group Assignment
You can access our group assignment here.
Individual Assignment
For this week also, I am planning to use the same board that I designed during week 8 π€
For this assignment, I want to make use of a 1.3-inch OLED display along with a buzzer π€ .
OLED
An OLED (Organic Light-Emitting Diode) display is a screen that can show text, graphics, and animations with bright and clear visuals, even in low light.
It operates on a volatge supply of 3.3V - 5V. The OLED display usually has four pins: VCC for the power supply, GND for ground, SCL for the clock signal used in communication, and SDA for the data signal that carries information.
How it works?
An OLED is made of many thin layers stacked together. At the bottom is the substrate (usually made of glass or flexible plastic) and this is what holds everything in place. On top of that is the anode, which helps current flow through the device. The middle part consists of the organic layers, which usually include a conductive layer that moves positive charges and an emissive layer where light is actually produced.
The top layer is the cathode which injects electrons into the organic layers so they can move toward the emissive layer. When these electrons meet the positive charges coming from the anode, they combine and release energy as light. Each pixel produces its own light when electricity passes through, allowing the display to show bright colors.
Buzzer
A buzzer is an output device that produces sound when electrical signals are applied.
It usually operates on a voltage supply of 3V - 5V. A basic buzzer has two pins: VCC for the power supply and GND for ground. Some buzzers also have a signal input to control different sound patterns.
How it works?
Inside, it contains either a piezoelectric element or a small electromagnetic coil with a diaphragm. In a piezo buzzer, applying voltage makes the material expand and contract rapidly which creates vibrations in the air that we hear as sound. In an electromagnetic buzzer, the current moves the diaphragm (Thin, flexible piece of material that can vibrate to create sound) back and forth to produce sound waves.
Each buzzer produces a specific tone, and by changing the signal or frequency, it can generate different sounds or even play simple melodies. This allows buzzers to give different audible feedback. π
There are two main types of buzzers: Active and Passive
Active Buzzer: An active buzzer has a built-in oscillator, so it only needs a DC voltage to make sound. You just have to connect it to power and it beeps on its own (Makes it super easy to use).
Passive Buzzer: A passive buzzer does not have an internal oscillator, so it needs an external signal (like a square wave from a microcontroller) to create sound. This lets you control the frequency, so you can make different tones or even play simple melodies. π΅
An oscillator is a circuit that generates a repeating signal (usually in the form of a wave) and can be used to create sound or control timing in electronic devices.
Using an OLED, a buzzer and my board, these are the connections I made:
Note: GPIO pins behave differently depending on whether theyβre sending or receiving signals. Sending, like turning on an LED, works easily because you control the voltage. Receiving, like detecting a button press, is trickier because noise or leftover voltages can interfere. Thatβs why I had to use an external button (instead of the onboard one) to make sure the pin gets a clear signal.OLED Connections
| OLED Pin | Connect to XIAO Pin | Type |
|---|---|---|
| VCC | 3.3V | Power |
| GND | GND | Ground |
| SDA | GPIO 6 | I2C |
| SCL | GPIO 7 | I2C |
Buzzer, Button, and LED Connections
| Component Pin | Connect to XIAO Pin | Type |
|---|---|---|
| Buzzer + | GPIO 9 | Digital Output |
| Buzzer - | GND | Ground |
| Button side 1 | GPIO 5 | Digital Input (with pull-up) |
| Button side 2 | GND | Ground |
| LED + (long leg) | GPIO 8 | Digital Output |
| LED - (short leg) | GND (through 220Ξ© resistor) | Ground |
Here is how the setup looks π:
Note: It is NOT at all recommended to use a breadboard π ββοΈ. However, I used one in my setup for the GND rail and the external button π€¦ββοΈ.
With this setup, I experimented with different codes and played different rhymes while displaying the lyrics as well π
Note: I asked ChatGPT to generate the code for each of the rhymes below (Credit to AIπ₯³π)
Clap, Clap, Clap, Tap
Prompt: Can you generate a code so that after I press a button, the OLED shows the lyrics for the Clap Tap rhyme in time with the buzzer and LED following the same rhythm?
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SDA_PIN 6
#define SCL_PIN 7
#define BUTTON_PIN 5
#define LED_PIN 8
#define BUZZER_PIN 21
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Rhythm durations (ms)
int beats[] = {
300,300, // Clap Clap
300,300, // Tap Tap
300,300,300, // Clap Tap Clap
800 // Stop (long)
};
// Words synced to beats
String words[] = {
"Clap", "Clap",
"Tap", "Tap",
"Clap", "Tap", "Clap",
"STOP!"
};
int totalNotes = 8;
void showText(String msg) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(10, 20);
display.print(msg);
display.display();
}
void playBeat(int duration) {
int beepTime = duration * 0.6;
int silenceTime = duration * 0.4;
// ON = sound + LED ON
digitalWrite(BUZZER_PIN, HIGH);
digitalWrite(LED_PIN, LOW);
delay(beepTime);
// OFF = silence + LED OFF
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_PIN, HIGH);
delay(silenceTime);
}
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
digitalWrite(BUZZER_PIN, LOW);
Wire.begin(SDA_PIN, SCL_PIN);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
showText("Press!");
}
void loop() {
if (digitalRead(BUTTON_PIN) == LOW) {
delay(50);
if (digitalRead(BUTTON_PIN) == LOW) {
for (int i = 0; i < totalNotes; i++) {
showText(words[i]); // Show word
playBeat(beats[i]); // Play rhythm
}
showText("Done!");
delay(1000);
// wait for button release
while (digitalRead(BUTTON_PIN) == LOW);
}
}
}
How does the code work? π€·ββοΈ
The code starts by importing the necessary libraries for the OLED display and setting up the display object. It also defines the pins for the button, LED, and buzzer on the board. In the setup() function, the pins are initialized: the button uses INPUT_PULLUP, while the LED and buzzer are set as outputs. The OLED display is also initialized to show messages.
Inside the loop() function, the code checks if the button is pressed. When pressed, it goes through a predefined sequence of beats and words. For each beat, it turns the buzzer on while the LED flashes for part of the duration, then turns them off for the remaining duration. At the same time, the OLED displays the word corresponding to that beat. This creates a synchronized combination of sound, light, and text. After completing the sequence, the display shows βDone!β and the program waits for the button to be released before allowing the sequence to play again.
Happy Birthday
Prompt: Can you generate a code so that after I press a button, my OLED shows the words of Happy Birthday word by word, while a buzzer plays the rhyme in sync and an LED blinks with each note?
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ββ Pin definitions ββββββββββββββββββββββββββββββ
#define SDA_PIN 6
#define SCL_PIN 7
#define BUTTON_PIN 5
#define LED_PIN 8
#define BUZZER_PIN 21
// ββ Display ββββββββββββββββββββββββββββββββββββββ
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ββ Notes ββββββββββββββββββββββββββββββββββββββββ
#define G4 392
#define A4 440
#define B4 494
#define C5 523
#define D5 587
#define E5 659
#define F5 698
#define G5 784
// ββ Song data ββββββββββββββββββββββββββββββββββββ
#define TOTAL_NOTES 25
int melody[TOTAL_NOTES] = {
G4, G4, A4, G4, C5, B4,
G4, G4, A4, G4, D5, C5,
G4, G4, G5, E5, C5, B4, A4,
F5, F5, E5, C5, D5, C5
};
int dur[TOTAL_NOTES] = {
300, 300, 500, 500, 500, 700,
300, 300, 500, 500, 500, 700,
300, 300, 500, 500, 500, 500, 700,
300, 300, 500, 500, 500, 700
};
const char* words[TOTAL_NOTES] = {
"Hap-", "py", "Birth-", "day", "to", "You!",
"Hap-", "py", "Birth-", "day", "to", "You!",
"Hap-", "py", "Birth-", "day", "Dear", "Fri-", "end!",
"Hap-", "py", "Birth-", "day", "to", "You!"
};
// ββ Show text on OLED βββββββββββββββββββββββββββββ
void showText(const char* msg) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 22);
display.print(msg);
display.display();
}
// ββ Play one note + flash LED βββββββββββββββββββββ
void playNote(int freq, int ms) {
tone(BUZZER_PIN, freq);
digitalWrite(LED_PIN, LOW); // LED ON
delay(ms - 40);
noTone(BUZZER_PIN);
digitalWrite(LED_PIN, HIGH); // LED OFF
delay(40); // short gap between notes
}
// ββ Play the whole song βββββββββββββββββββββββββββ
void playSong() {
for (int i = 0; i < TOTAL_NOTES; i++) {
showText(words[i]);
playNote(melody[i], dur[i]);
}
showText("Done! :)");
delay(2000);
showText("Press btn!");
}
// βββββββββββββββββββββββββββββββββββββββββββββββββ
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH); // LED off
Wire.begin(SDA_PIN, SCL_PIN);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
// OLED failed β blink LED forever so you know
while (true) {
digitalWrite(LED_PIN, LOW);
delay(200);
digitalWrite(LED_PIN, HIGH);
delay(200);
}
}
showText("Press btn!");
}
void loop() {
if (digitalRead(BUTTON_PIN) == LOW) {
delay(60); // debounce
if (digitalRead(BUTTON_PIN) == LOW) {
playSong();
while (digitalRead(BUTTON_PIN) == LOW); // wait for release
}
}
}
How does the code work? π€·ββοΈ
The code begins by importing the necessary libraries for the OLED display and defining the pins for the button, LED, and buzzer on the board. The OLED display object is created to handle text output. In the setup() function, the button is configured with INPUT_PULLUP, and the LED and buzzer are set as outputs. The display is initialized, and a βPress btn!β message appears to prompt the user to start.
Inside the loop() function, the program waits for the button to be pressed. Once pressed, it loops through a predefined sequence of musical notes and corresponding words for the βHappy Birthdayβ song. For each note, the buzzer produces the sound while the LED flashes, and the OLED shows the word synchronized with the note. After completing all the notes, the display shows βDone!β and waits for a short pause before prompting the user again. The program also ensures the button is released before allowing another playthrough.
Johny Johny
Prompt: Can you make a program so that when I press a button, the OLED displays the lyrics of Johny Johny Yes Papa while a buzzer plays the tune and an LED blinks along with each note?
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ββ Pin definitions ββββββββββββββββββββββββββββββ
#define SDA_PIN 6
#define SCL_PIN 7
#define BUTTON_PIN 5
#define LED_PIN 8
#define BUZZER_PIN 21
// ββ Display ββββββββββββββββββββββββββββββββββββββ
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ββ Notes ββββββββββββββββββββββββββββββββββββββββ
#define C4 262
#define D4 294
#define E4 330
#define F4 349
#define G4 392
#define A4 440
#define B4 494
#define C5 523
// ββ Song data ββββββββββββββββββββββββββββββββββββ
int melody[] = {
C4, E4, G4, C5,
G4, A4, G4,
E4, F4, E4, D4,
E4, D4, C4,
G4, A4, B4,
C5, B4, A4,
G4, E4, F4, G4,
C5, C5, C5,
C4, E4, G4, C5,
G4, A4, G4,
E4, G4, C5,
C5, B4, C5
};
int dur[] = {
400, 400, 400, 600,
400, 400, 700,
400, 400, 400, 600,
400, 400, 700,
400, 400, 600,
400, 400, 700,
400, 400, 400, 600,
300, 300, 700,
400, 400, 400, 600,
400, 400, 700,
300, 300, 600,
300, 300, 900
};
const char* words[] = {
"Joh-", "ny", "Joh-", "ny!",
"Yes", "Pa-", "pa!",
"Eat-", "ing", "su-", "gar?",
"No", "Pa-", "pa!",
"Tel-", "ling", "lies?",
"No", "Pa-", "pa!",
"O-", "pen", "your", "mouth!",
"Ha", "ha", "ha!",
"Joh-", "ny", "Joh-", "ny!",
"Yes", "Pa-", "pa!",
"Ha", "ha", "ha!",
"Ha", "ha", "ha!!!"
};
// Automatically get total notes
int totalNotes = sizeof(melody) / sizeof(melody[0]);
// ββ Show text on OLED βββββββββββββββββββββββββββββ
void showText(const char* msg) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 22);
display.print(msg);
display.display();
}
// ββ Play one note + flash LED βββββββββββββββββββββ
void playNote(int freq, int ms) {
tone(BUZZER_PIN, freq);
digitalWrite(LED_PIN, LOW);
delay(ms - 40);
noTone(BUZZER_PIN);
digitalWrite(LED_PIN, HIGH);
delay(40);
}
// ββ Play the whole song βββββββββββββββββββββββββββ
void playSong() {
for (int i = 0; i < totalNotes; i++) {
showText(words[i]);
playNote(melody[i], dur[i]);
}
showText("Ha ha ha!");
delay(1000);
showText("Done! :)");
delay(2000);
showText("Press btn!");
}
// βββββββββββββββββββββββββββββββββββββββββββββββββ
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
Wire.begin(SDA_PIN, SCL_PIN);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
How does the code work? π€·
Like the two above codes above, this code starts by importing the necessary libraries to control the OLED display and defining the pins for the button, LED, and buzzer. The OLED display object is created using Adafruit_SSD1306 to manage text output. In the setup() function, the button is configured with INPUT_PULLUP to detect presses, and the LED and buzzer are set as outputs. The OLED display is initialized, and if initialization fails, the LED blinks repeatedly to indicate an error. Once the setup is complete, the display shows βPress btn!β to prompt the user.
Inside the loop() function, the code continuously checks if the button is pressed. When pressed, it calls the playSong() function and waits for the button to be released before allowing the song to play again. The playSong() function loops through a predefined sequence of musical notes and corresponding words for the βJohny Johnyβ rhyme. For each note, the buzzer produces sound while the LED flashes, and the OLED shows the matching syllable, keeping the text synchronized with the audio and visual signals. After completing the song, the display shows βHa ha ha!β, then βDone! :)β, and finally prompts the user again to press the button.
I had a great time this week. There wasn't a lot of stress about finishing the assignment quickly so I could genuinely focus on and enjoy the whole process.π
