Wave Drawer
Wave Drawer
What I wanted to learn, and why it interested me: I learned how to use an OLED screen on an Arduino and how to figure out its pins for exporting data properly. This interested me given I have an art background and can now control and draw
Final outcome: A line of points is generated across the OLED screen that can be changed. Using two potentiometers, you can control the scroll speed and adjust where the next point shall be placed. Note the points scroll to the left.
Images of final creative/exploratory output
Final wave drawing in practice.
Final Wiring, top view.
Process images from development towards creative/exploratory output
Early drawing test.
Wiring midway.
Process and reflection:
The longest part was the issue of the screen having an odd address. What this means is when I plugged in the OLED screen an issue a raised where despite being 64 × 128 pixels it was using the same address as a 32 × 128 screen. The address is used in the code to export data to the screen successfully. Beyond this, the next issue was removing the delay and adding a subtle but needed detail of showing the user where their line was going to draw without it feeling sluggish. To be specific, earlier in development the speed control was a simple delay in the loop but was changed to an if statement that would change the array data once enough time passed. Adding this was simple in hindsight, but had small, time-consuming issues.
Technical details
Function Diagram and Electrical Scheme
/*
60-223 Intro to Physical Computing, fall 2025
Wave Drawer
This code uses an OLED screen to display a wave drawing. The wave is based on the
input of a potentiometer to determine the points of the wave. The second
potentiometer is used to control the speed of the wave scrolling to the left.
Pin mapping:
Arduino pin | role | details
------------------------------
A0 input potentiometer
A1 input potentiometer
A4,A5 output OLED screen
Released to the public domain by the author, October 2025
G Meloche
*/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
const static uint16_t POTENT_PIN = A0;
const static uint16_t POTENT_PIN_2 = A1;
const static uint8_t SCREEN_WIDTH = 128;
const static uint8_t SCREEN_HEIGHT = 64;
static uint8_t pixelArray [SCREEN_WIDTH];
static uint32_t WAIT_TIME = 0;
static uint32_t timeRecorded = 0;
// Arduino UNO: A4(SDA), A5(SCL)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define LOGO_HEIGHT 16
void setup() {
pinMode (POTENT_PIN, INPUT);
pinMode (POTENT_PIN_2, INPUT);
Serial.begin(9600);
while (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
delay (300);
}
Serial.println ("SSD1306 allocation success");
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(1100); // Pause for 1.1 seconds
// Clear the buffer
display.clearDisplay();
display.display();
arraySetup();
}
void loop(void) {
uint8_t potentVal = analogRead (POTENT_PIN);
uint8_t mappedPotentVal = map (potentVal, 0, 255, 0, SCREEN_HEIGHT-1);
// Used to display what point will be drawn
pixelArray[SCREEN_WIDTH-1] = mappedPotentVal;
uint32_t currentTime = millis();
if (currentTime - timeRecorded >= WAIT_TIME){
arraySetNewVal (mappedPotentVal);
timeRecorded = millis();
}
drawArray();
uint16_t potentVal2 = analogRead (POTENT_PIN_2);
WAIT_TIME = map (potentVal2, 0, 1023, 400, 0);
}
void arraySetup (void){
for (uint8_t i = 0; i < SCREEN_WIDTH; i++)
pixelArray[i] = 0;
}
void arraySetNewVal (uint8_t newY){
for (uint8_t i = 0; i < SCREEN_WIDTH - 1; i++)
pixelArray[i] = pixelArray[i+1];
pixelArray[SCREEN_WIDTH - 1] = newY;
}
void drawArray(void){
uint8_t prevX = 0;
uint8_t prevY = pixelArray[prevX];
uint8_t y;
display.clearDisplay();
for (uint8_t x = 0; x < SCREEN_WIDTH; x++){
y = pixelArray[x];
display.drawLine (prevX, prevY, x, y, WHITE);
prevX = x;
prevY = y;
}
display.display();
}