I wanted to learn how to use a pixel display because growing up I loved to play Nintendo and always wondered how they were able to make the characters move and be shown on the screen. I also wanted to make something creative for my younger cousins who wondered the same thing. Also, using a pixel display gave me a way to learn how to use an arcade button and a rocker switch which I was really excited about!
Final Outcome: I was able to create hearts and text with the pixel display. The button let me change the screen to show other text, and the switch turned the display on and off. I went beyond what I thought I was capable of by using Fusion to design a box where I could easily fit the circuit, with the display, button, and switch on top. I also learned how to add images in Fusion so I could fully personalize the box with the things my younger cousin loves.
Images of Final Creative/Exploratory Output
This the final video of the pixel display, button and switch working.
This is the final with box and the everything displayed. The pixel display is on the top, the button is on the front and the switch is in the right.
Process images from development towards creative/exploratory output
Trying to get the pixel display to respond to the switch and button.
Putting everything together and attaching it to the wood while making sure eveything is still working simultaneously.
Process and reflection:
When I started this project, the very first thing I did was connect the pixel display straight to my Arduino just to see if it would even turn on. I’ll never forget the moment it finally printed “hello” with the help of ChatGPT. Seeing that happen made me really excited to keep building. From there, I wanted to try something more interactive, so I researched how to wire up the arcade button. After a bit of trial and error, I got it working, and soon I was able to program messages that changed every time the button was pressed. Adding the switch to turn the display on and off was the next step, and it made the whole setup complete.
Once the electronics were working, I moved on to Fusion to design the box. That was a challenge on its own. It took me several tries, lots of starting over, and plenty of patience. Eventually I figured out how to design it so the display, button, and switch all fit(nearly). I even learned how to add images so I could personalize the box with things my younger cousin loves. The hardest parts were getting the display to even turn on and building the box in Fusion, but both of those struggles pushed me to learn so much more. Looking back, I’m proud I stuck with it, because I not only learned new skills but also created something meaningful that I can share with my cousin.
Technical details
Pixel Display Electrical schematic
(The 9V power came from a battery, not drawn)
/*
60-223 Intro to Physical Computing, fall 2025
Domain-specific Skill Building exercise: Pixel Display
This sketch connects an OLED pixel display (via I2C: SDA, SCL),
an arcade button, and a rocker switch. The display shows
personalized text messages with hearts and symbols. Each time
the arcade button is pressed, the screen cycles to the next
message. The rocker switch is used to turn the display on and off.
Pin mapping:
Arduino pin | role | details
------------------------------------
2 | input | arcade button
3 | input | rocker switch
SDA/A4 | I2C | OLED display
SCL/A5 | I2C | OLED display
Released to the public domain by the author, September 2025
Danely Rodriguez, danelyr@andrew.cmu.edu
Prompt used for ChatGPT: I want you to write me a complete Arduino
sketch for an SSD1306 OLED display (128x64 I2C) with
one arcade pushbutton on pin D2 and one toggle switch on pin D3.
The switch should act as an on/off: when it’s off the screen is blank,
and when I flip it on it should first show a startup screen for two seconds
with a big filled heart in the center, “Hi Luna!” written bold in size 2 and
centered across the screen in black text on a white background so it’s
readable, plus small hearts in each corner. After that, pressing the arcade
button should cycle through three bold messages: “I love you Luna” with two hearts on
the right, “I miss you my little cousin” with one heart at the bottom right,
and “I’m so proud of you Lulu!” with three hearts stacked on the right. Each button press
should change to the next message, looping back to the start.
*/
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define BUTTON_PIN 2
#define SWITCH_PIN 3
int messageIndex = 0;
bool lastButtonState = HIGH;
bool lastSwitchState = HIGH;
// ------------------- HEART BITMAP -------------------
const unsigned char heart_bmp [] PROGMEM = {
0b00001100, 0b00110000,
0b00011110, 0b01111000,
0b00111111, 0b11111100,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b00111111, 0b11111100,
0b00011111, 0b11111000,
0b00001111, 0b11110000,
0b00000111, 0b11100000,
0b00000011, 0b11000000,
0b00000001, 0b10000000,
0b00000000, 0b00000000
};
// ------------------- BOLD TEXT HELPER -------------------
void printBold(const char *text, int x, int y, int size, bool invert = false) {
display.setTextSize(size);
if (invert) {
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
display.setTextColor(SSD1306_WHITE);
}
// Draw text multiple times slightly offset to thicken (bold effect)
display.setCursor(x, y);
display.print(text);
display.setCursor(x+1, y);
display.print(text);
display.setCursor(x, y+1);
display.print(text);
}
// ------------------- MESSAGES -------------------
void showMessage(int index) {
display.clearDisplay();
if (index == 0) {
printBold("I love", 0, 0, 2);
printBold("you Luna", 0, 25, 2);
display.drawBitmap(100, 0, heart_bmp, 16, 16, SSD1306_WHITE);
display.drawBitmap(100, 40, heart_bmp, 16, 16, SSD1306_WHITE);
}
else if (index == 1) {
printBold("I miss you", 0, 0, 2);
printBold("my little", 0, 22, 2);
printBold("cousin", 0, 44, 2);
display.drawBitmap(110, 40, heart_bmp, 16, 16, SSD1306_WHITE);
}
else if (index == 2) {
printBold("I'm so", 0, 0, 2);
printBold("proud of", 0, 22, 2);
printBold("you Lulu!", 0, 44, 2);
display.drawBitmap(90, 0, heart_bmp, 16, 16, SSD1306_WHITE);
display.drawBitmap(110, 20, heart_bmp, 16, 16, SSD1306_WHITE);
display.drawBitmap(90, 40, heart_bmp, 16, 16, SSD1306_WHITE);
}
display.display();
}
// ------------------- STARTUP SCREEN -------------------
void showStartup() {
display.clearDisplay();
// Big heart background
display.fillCircle(48, 20, 18, SSD1306_WHITE);
display.fillCircle(80, 20, 18, SSD1306_WHITE);
display.fillTriangle(30, 28, 98, 28, 64, 62, SSD1306_WHITE);
// Measure text bounds to center "Hi Luna!"
int16_t x1, y1;
uint16_t w, h;
display.setTextSize(2);
display.getTextBounds("Hi Luna!", 0, 0, &x1, &y1, &w, &h);
int16_t x = (SCREEN_WIDTH - w) / 2;
int16_t y = 22;
// Bold "Hi Luna!" in center (inverted so it stands out on the heart)
printBold("Hi Luna!", x, y, 2, true);
// Corner hearts
display.drawBitmap(0, 0, heart_bmp, 16, 16, SSD1306_WHITE);
display.drawBitmap(112, 0, heart_bmp, 16, 16, SSD1306_WHITE);
display.drawBitmap(0, 48, heart_bmp, 16, 16, SSD1306_WHITE);
display.drawBitmap(112, 48, heart_bmp, 16, 16, SSD1306_WHITE);
display.display();
delay(2000);
}
// ------------------- SETUP -------------------
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(SWITCH_PIN, INPUT_PULLUP);
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
for(;;); // loop forever if screen fails
}
display.clearDisplay();
showMessage(messageIndex);
}
// ------------------- LOOP -------------------
void loop() {
bool switchState = digitalRead(SWITCH_PIN);
if (switchState == HIGH) {
display.clearDisplay();
display.display();
lastSwitchState = HIGH;
return;
}
if (lastSwitchState == HIGH && switchState == LOW) {
showStartup();
showMessage(messageIndex);
}
bool buttonState = digitalRead(BUTTON_PIN);
if (lastButtonState == HIGH && buttonState == LOW) {
messageIndex++;
if (messageIndex > 2) messageIndex = 0;
showMessage(messageIndex);
delay(200);
}
lastButtonState = buttonState;
lastSwitchState = switchState;
}