Graham Pullin’s Design Meets Disability made me reflect on how design often operates in rigid categories, medical vs. fashionable, functional vs. expressive, and how these binaries fail people with disabilities. The reading’s core idea, that assistive tools deserve the same creative energy as mainstream products, feels both radical and obvious. Why shouldn’t a wheelchair or hearing aid reflect personal style? Glasses, after all, evolved from clunky necessities to fashion statements, proving that utility and aesthetics can coexist.
But I also doubted the practicality of this vision. While stylish prosthetics or colorful hearing aids could challenge stigma, design alone can’t dismantle systemic barriers like inaccessible infrastructure or costs. As one sample response noted, a sleek wheelchair might still be seen as “other” in a world built for stairs. And prioritizing aesthetics risks alienating those who need simplicity or affordability—like how designer eyewear can become unaffordable luxury. Still, Pullin isn’t arguing for style over function but for expanding what’s possible. His examples, like voice synthesizers with emotional nuance, show that “inclusive design” isn’t about trends but dignity: tools should empower users to feel seen, not hidden.
What sticks with me is the tension between individuality and universality. While choice is empowering, too many options can overwhelm. Yet Pullin’s call for diversity in design, discreet or bold, high-tech or minimalist, mirrors the broader disability experience: there’s no single “right” way to navigate the world. Maybe the goal isn’t to make assistive tools “mainstream” but to normalize their presence in design conversations. After all, glasses weren’t normalized by hiding them but by celebrating their versatility. Disability isn’t a niche market – it’s a lens (pun intended) through which we can rethink design for everyone.
void setup(){
Serial.begin(9600);
}
void loop(){
int pot = analogRead(A0);
// Less responsive: smaller output range
int xPos = map(pot, 0, 1023, 100, 300);
Serial.println(xPos);
delay(100); // longer delay = slower updates
}
Challenges:
It was difficult to make the ball move gradually, this was an issue with the p5.js sketch and we added a smoothing factor to make the movement more ideal.
Exercise 2:
Arduino Code:
// Arduino: LED brightness via Serial input
const int ledPin = 6;
const unsigned long BAUD = 9600;
void setup() {
Serial.begin(BAUD);
while (!Serial) ; // wait for Serial Monitor
pinMode(ledPin, OUTPUT);
Serial.println("LED Brightness Control");
Serial.println("Send a number 0–255, then <Enter>:");
}
void loop() {
// only proceed if we have a full line
if (Serial.available()) {
String line = Serial.readStringUntil('\n');
line.trim(); // remove whitespace
if (line.length() > 0) {
int b = line.toInt();
b = constrain(b, 0, 255);
analogWrite(ledPin, b);
Serial.print("▶ Brightness set to ");
Serial.println(b);
}
}
}
// Fade smoothly to a target brightness
void fadeTo(int target, int speed = 5, int delayMs = 10) {
int curr = 0;
// read current duty by trial (not perfect, but illustrates the idea)
for (int i = 0; i < 256; i++) {
analogWrite(ledPin, i);
if (i == target) {
curr = i;
break;
}
}
while (curr != target) {
curr += (target > curr) ? speed : -speed;
curr = constrain(curr, 0, 255);
analogWrite(ledPin, curr);
delay(delayMs);
}
}
Challenges:
For this exercise the challenges were 1: making the gradient slider animation look intuitive for functionality, and we spent a lot of time debating on whether a rainbow slider was cool or not. We decided that it was.
Exercise 3:
For this exercise we decided to build on the example provided and improve the physics of the wind as well as the animation of the ball itself. To keep track of the sensor values and ensure we are receiving consistent results, we included variables to track the potentiometer, bounce (1 results in LED high, 0 results in LED low) and the mass is just an added feature.
Challenges:
The issues we faced were plenty, including making the wind seem more realistic and making the interaction smoother. The first approach to solve this challenge were to implement debounce to discard those operations that would occur too closely during the runtime interval. We also had to be particularly careful about how often the p5.js asks for the potentiometer reading, considering the frequency of the frames displaying the visual text and the frequency of the potentiometer reading.
Arduino Code:
const int LED_PIN = 9; // LED pin
const int P_PIN = A0; // Potentiometer pin
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW); // Initial LED state
// Handshake: Wait for p5.js to send a start signal
while (Serial.available() <= 0) {
Serial.println("INIT"); // Send "INIT" until p5.js responds
delay(100); // Avoid flooding
}
}
void loop() {
// Check for incoming serial data
if (Serial.available() > 0) {
char incoming = Serial.read(); // Read a single character
if (incoming == 'B') { // p5.js sends 'B' followed by 0 or 1
while (Serial.available() <= 0); // Wait for the value
int bounce = Serial.read() - '0'; // Convert char '0' or '1' to int
digitalWrite(LED_PIN, bounce); // Set LED (0 = LOW, 1 = HIGH)
}
else if (incoming == 'R') { // p5.js requests potentiometer reading
int potValue = analogRead(P_PIN); // Read potentiometer (0-1023)
Serial.println(potValue); // Send value
}
// Clear any remaining buffer (e.g., newlines)
while (Serial.available() > 0) {
Serial.read();
}
}
}
In this setup, I connected a photoresistor to analog pin A0 of the Arduino. The changing light levels (e.g., when I moved my hand closer or farther) were read via analog input and sent to p5.js over serial communication. In p5.js, the light level was mapped to a horizontal position (X-axis) of an ellipse on screen.
As a result, the ellipse smoothly moved left to right based on how much light was detected by the sensor. The Arduino was a pure input device in this task, with no output components involved.
// Arduino Code for Photocell -> Horizontal Ellipse
const int photoPin = A0;
void setup() {
Serial.begin(9600);
}
void loop() {
int lightLevel = analogRead(photoPin);
Serial.println(lightLevel);
delay(50); // small delay for stability
}
//Javascript:
let serial;
let latestData = "0";
function setup() {
createCanvas(400, 400);
serial = new p5.SerialPort();
serial.open("/dev/tty.usbmodem13301");
serial.on("data", () => {
latestData = serial.readLine().trim();
});
}
function draw() {
background(220);
let x = map(Number(latestData), 0, 1023, 0, width);
ellipse(x, height/2, 50, 50);
}
Task 2: LED Brightness Controller
This task reverses the direction of interaction from Task 1. A slider on the p5.js canvas sends values (0–255) to Arduino via serial. The Arduino reads these values and writes them to a PWM pin controlling an LED, adjusting brightness in real-time.
As a result, once the slider was adjusted, the LED smoothly brightened or dimmed, creating a tangible link between screen-based and physical interaction.
// Arduino Code for LED brightness control
const int ledPin = 9;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
if (Serial.available()) {
int brightness = Serial.parseInt();
analogWrite(ledPin, brightness);
}
}
//Javascript
let serial;
let slider;
function setup() {
createCanvas(400, 200);
slider = createSlider(0, 255, 127);
slider.position(20, 20);
serial = new p5.SerialPort();
serial.open("/dev/tty.usbmodem13301");
}
function draw() {
background(255);
let val = slider.value();
text("Brightness: " + val, 20, 70);
serial.write(val + "\n");
}
Task 3: Bouncing Ball
For this task, I modified the Gravity + Wind example from p5.js. A photocell connected to Arduino reads ambient light and sends it to p5.js to control the “wind” vector pushing up on the ball. Simultaneously, when the ball hits the bottom of the canvas, p5.js sends a “BOUNCE” signal back to Arduino, briefly lighting up an LED.
In the end, the ball was bouncing realistically, with its movement affected by how much I covered the photocell. Each bounce triggered a short LED flash, adding physical feedback to a digital interaction.
// Alternate: if p5 sends a "bounce" message, flash LED
const int ledPin = 9;
const int photoPin = A0;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
int light = analogRead(photoPin);
Serial.println(light);
delay(10);
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
if (command == "BOUNCE") {
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
}
}
}
//Javascript
let serial;
let position, velocity, acceleration;
let gravity, wind;
let drag = 0.99;
let mass = 50;
let photoresistorValue = 0;
function setup() {
createCanvas(640, 360);
position = createVector(width / 2, 0);
velocity = createVector(0, 0);
acceleration = createVector(0, 0);
gravity = createVector(0, 0.5 * mass);
wind = createVector(0, 0);
serial = new p5.SerialPort();
serial.open("/dev/tty.usbmodem13301");
serial.on("data", () => {
let data = serial.readLine().trim();
if (!data) return;
photoresistorValue = int(data);
});
}
function draw() {
background(255);
wind.y = map(photoresistorValue, 0, 1023, -2, 0); // More wind when covered
applyForce(gravity);
applyForce(wind);
velocity.add(acceleration);
velocity.mult(drag);
position.add(velocity);
acceleration.mult(0);
// Bounce
if (position.y > height) {
position.y = height;
velocity.y *= -1;
serial.write("BOUNCE\n"); // Trigger LED
}
ellipse(position.x, position.y, 50, 50);
}
function applyForce(force) {
let f = p5.Vector.div(force, mass);
acceleration.add(f);
}
Reflection:
This set of projects helped me understand both unidirectional and bidirectional interactions between hardware and software. The exercises showed how to turn real-world stimuli into digital visuals and vice versa, laying the groundwork for interactive installations, responsive art, or assistive interfaces, which is a great practice for the final project.
Reading Assignment
Reading Design Meets Disability made me rethink how design often treats disability as something to minimize or fix, rather than as an opportunity for creative expression. Pullin’s argument that assistive technologies like hearing aids or prosthetics can be expressive and personal, not just functional has really stuck with me. It challenged the default idea in my head that good design is neutral or invisible, and instead made me see how thoughtful design can actually expand what’s possible for people with disabilities.
This reminded me of Sophie de Oliveira Barata’s work, which we studied in my Communication and Technology class. Through the Alternative Limb Project, she creates prosthetics that are more than medical devices but rather artistic statements. Some are realistic, others are completely imaginative, with embedded lights or sculptural elements. Her work makes it clear that prosthetics can reflect someone’s identity and creativity, not just their physical needs. It’s a powerful example of how design can shift the narrative from limitation to self-expression.
Both Pullin’s book and Sophie’s work pushed me to question what we mean by “inclusive” or “accessible” design. It made me realize that good design goes beyond functionality by also giving people choices, visibility, and agency. I’m beginning to see inclusive design not as a constraint, but as a more thoughtful and exciting way to approach creative work.
Concept: My final project is a physically interactive zombie shooting game that uses a laser pointer and photoresistors (light sensors) to detect hits. The player uses a toy gun or pointer that emits a laser beam to “shoot” zombies that appear randomly. On a physical board, multiple photoresistors are positioned with LEDs next to them, each representing a zombie spawn point. When a zombie appears, an LED lights up, and the player must aim the laser pointer at that sensor to “kill” the zombie. The interaction is fast-paced and relies on quick aiming and physical movement, combining real-world action with digital feedback.
Arduino’s Role: The Arduino is responsible for controlling the game logic on the hardware side. It randomly selects which LED to turn on, simulating a zombie “appearing” in that location. It continuously reads data from the photoresistors to detect when a laser beam hits the correct sensor. When a hit is detected, the Arduino confirms the zombie has been shot, turns off the LED, and sends the information to P5.js (such as which zombie was hit and the reaction time). It can also keep track of hits and misses, and control the timing of zombie spawns to make the game more challenging as it progresses.
P5.js Display: P5.js will serve as the visual part of the game, showing animated zombies that match the LEDs lighting up on the physical board. When the Arduino tells P5 a zombie has appeared (LED turned on), a zombie image will pop up in the corresponding location on the screen. When the player successfully shoots the sensor with the laser, the zombie will disappear with a simple animation, like falling down or exploding. The game will display the player’s score, reaction time for each shot, and lives or missed zombies. It can also play sound effects for hits and misses, and include a game over screen when the player fails to shoot zombies in time.
For my final project, I am creating an interactive audiovisual system called ExpressNotes, which combines sound, visuals, and physical input to encourage real-time artistic expression. The system uses an Arduino with four push buttons and a potentiometer. Each button press plays a different piano note, while the potentiometer adjusts the volume. These physical actions are detected by the Arduino and sent to a P5.js sketch running on a multimedia computer. The P5 environment generates visual effects on screen that correspond to each note, creating a dynamic and evolving piece of generative art based on the user’s input.
This project is designed to facilitate an engaging, expressive loop between the user and the system. The Arduino listens to physical interactions—button presses and volume control—and transmits that information instantly. The P5.js sketch interprets the input by producing synchronized audio and visuals. For example, pressing a specific button might trigger a ripple of blue circles with a soft C note, while another might launch animated triangles with a brighter tone. The visual and auditory elements work in tandem, offering immediate and meaningful feedback that makes the experience immersive and rewarding.
ExpressNotes emphasizes creativity and emotional engagement over precision or performance. The user is both musician and painter, creating a personal composition each time they interact with the system. The careful timing of responses ensures the interaction feels fluid and intuitive, and the unique art generated can be saved or shared. This project demonstrates the power of combining physical sensors with real-time multimedia output to create a space for individual expression that is playful, responsive, and visually compelling.
So for my final project, I have decided to create a game called ‘Code Red’, and it’s like a bomb defusal game where players race against time to solver certain challenges before time runs out and each challenge the player successfully completely, one digit of the code is revealed to them. Once they have completed all challenges successfully, they will have to enter the numbers which were revealed to them at the end of each challenge and if they enter the correct code before time runs out, they have defused the bomb.
The Arduino will handle the hardware side:
Reading button inputs, knob rotation, etc.
Lighting LEDs to indicate bomb status
Using a buzzer for alerts, errors, and countdown tension
p5js will handle the visual and game logic:
Showing the bomb interface, countdown timer, and progress (how many challenges completed)
Giving feedback (success/fail) for each challenge
Triggering animations and effects based on player actions
void setup(){
Serial.begin(9600);
}
void loop(){
int pot = analogRead(A0);
// Less responsive: smaller output range
int xPos = map(pot, 0, 1023, 100, 300);
Serial.println(xPos);
delay(100); // longer delay = slower updates
}
Challenges:
It was difficult to make the ball move gradually, this was an issue with the p5.js sketch and we added a smoothing factor to make the movement more ideal.
Video:
Exercise 2:
Arduino Code:
// Arduino: LED brightness via Serial input
const int ledPin = 6;
const unsigned long BAUD = 9600;
void setup() {
Serial.begin(BAUD);
while (!Serial) ; // wait for Serial Monitor
pinMode(ledPin, OUTPUT);
Serial.println("LED Brightness Control");
Serial.println("Send a number 0–255, then <Enter>:");
}
void loop() {
// only proceed if we have a full line
if (Serial.available()) {
String line = Serial.readStringUntil('\n');
line.trim(); // remove whitespace
if (line.length() > 0) {
int b = line.toInt();
b = constrain(b, 0, 255);
analogWrite(ledPin, b);
Serial.print("▶ Brightness set to ");
Serial.println(b);
}
}
}
// Fade smoothly to a target brightness
void fadeTo(int target, int speed = 5, int delayMs = 10) {
int curr = 0;
// read current duty by trial (not perfect, but illustrates the idea)
for (int i = 0; i < 256; i++) {
analogWrite(ledPin, i);
if (i == target) {
curr = i;
break;
}
}
while (curr != target) {
curr += (target > curr) ? speed : -speed;
curr = constrain(curr, 0, 255);
analogWrite(ledPin, curr);
delay(delayMs);
}
}
Challenges:
For this exercise the challenges were 1: making the gradient slider animation look intuitive for functionality, and we spent a lot of time debating on whether a rainbow slider was cool or not. We decided that it was.
Exercise 3:
For this exercise we decided to build on the example provided and improve the physics of the wind as well as the animation of the ball itself. To keep track of the sensor values and ensure we are receiving consistent results, we included variables to track the potentiometer, bounce (1 results in LED high, 0 results in LED low) and the mass is just an added feature.
Challenges:
The issues we faced were plenty, including making the wind seem more realistic and making the interaction smoother. The first approach to solve this challenge were to implement debounce to discard those operations that would occur too closely during the runtime interval. We also had to be particularly careful about how often the p5.js asks for the potentiometer reading, considering the frequency of the frames displaying the visual text and the frequency of the potentiometer reading.
Arduino Code:
const int LED_PIN = 9; // LED pin
const int P_PIN = A0; // Potentiometer pin
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW); // Initial LED state
// Handshake: Wait for p5.js to send a start signal
while (Serial.available() <= 0) {
Serial.println("INIT"); // Send "INIT" until p5.js responds
delay(100); // Avoid flooding
}
}
void loop() {
// Check for incoming serial data
if (Serial.available() > 0) {
char incoming = Serial.read(); // Read a single character
if (incoming == 'B') { // p5.js sends 'B' followed by 0 or 1
while (Serial.available() <= 0); // Wait for the value
int bounce = Serial.read() - '0'; // Convert char '0' or '1' to int
digitalWrite(LED_PIN, bounce); // Set LED (0 = LOW, 1 = HIGH)
}
else if (incoming == 'R') { // p5.js requests potentiometer reading
int potValue = analogRead(P_PIN); // Read potentiometer (0-1023)
Serial.println(potValue); // Send value
}
// Clear any remaining buffer (e.g., newlines)
while (Serial.available() > 0) {
Serial.read();
}
}
}
Reading Design Meets Disability really made me rethink the way we approach assistive devices and design in general. We often talk about design in terms of making things beautiful, sleek, and desirable, but when it comes to tools meant for disabled individuals, the conversation suddenly shifts to pure function. This reading flips that on its head. It challenges the idea that products like hearing aids, prosthetic limbs, and wheelchairs should be discreet or invisible. Instead, it argues that they deserve the same thoughtful, creative attention as a pair of glasses or a smartphone. Why shouldn’t a wheelchair be stylish? Why can’t a prosthetic leg be a bold expression of identity? Nowadays, this sort of mindset has become even more relevant, where people are proud to talk about and display their disabilities; they are no longer a matter of stigma.
What stood out to me most was how this reading doesn’t see disability as something to hide or fix, it sees it as a space full of untapped potential for design. The reading uses real-world examples and poses fascinating questions that got me thinking: what if hearing aids were designed with the same care and flair as high-end earphones? What if voice synthesizers had more emotional range and didn’t all sound like robots? This vision of inclusive design isn’t just about making things accessible; it’s about making them desirable. That’s a big difference. It’s not about helping people fit into a narrow idea of “normal”, but rather it’s about expanding what we think is normal to include a wider range of human experience and expression.
For my final project, I’m creating a game called “Repeat After Me”, a retro-themed memory and reaction game where the player has to copy a sequence of flashing lights using physical buttons. It’s inspired by classic toys like Hasbro’s Simon Says, which I was obsessed with as a child, but I’m adding my own twist with pixel-style visuals, fun audio feedback, and progressively faster, more challenging rounds.
I’ve always enjoyed games that involve rhythm, timing, or quick reactions, and I wanted to build something that feels tactile and engaging but also visually playful.
Arduino will handle the hardware side:
Lighting up colored LEDs in random sequences
Reading button presses from the player
Using a buzzer for physical feedback
p5.js will handle the visual and audio feedback:
Displaying the current score and level
Giving real-time responses to player input with sound and screen effects
Showing a title screen, countdown, and game over screen
Overall, I want this project to feel playful, fast-paced, and satisfying to interact with.
/*
* Week 11 Production (1)
*
* Inputs:
* - A1 - 10k potentiometer connected to 5V and GND
*
*/
int interval = 100;
int lastMessageTime = 0;
int potPin = A1;
void setup() {
Serial.begin(9600); // initialize serial communications
}
void loop() {
// read the input pin:
int potentiometer = analogRead(potPin);
// remap the pot value to 0-255:
int mappedPotValue = map(potentiometer, 0, 1023, 0, 255);
// print the value to the serial port.
Serial.println(mappedPotValue);
// slight delay to stabilize the ADC:
delay(1);
delay(100);
}
let port;
let connectBtn;
let baudrate = 9600;
let lastMessage = "";
let currX;
function setup() {
createCanvas(400, 400);
background(220);
port = createSerial();
let usedPorts = usedSerialPorts();
if (usedPorts.length > 0) {
port.open(usedPorts[0], baudrate);
}
connectBtn = createButton("Connect to Arduino");
connectBtn.position(80, height-60);
connectBtn.mousePressed(connectBtnClick);
currX = width/2;
}
function draw() {
background("white");
fill('grey');
circle(currX, height/2, 100);
let str = port.readUntil("\n");
if (str.length > 0) {
// console.log(str);
lastMessage = str;
}
// Display the most recent message
text("Last message: " + lastMessage, 10, height - 20);
// change button label based on connection status
if (!port.opened()) {
connectBtn.html("Connect to Arduino");
} else {
connectBtn.html("Disconnect");
}
// // Move shape based on received value
if (!lastMessage) {lastMessage = "127"}
currX = map(int(lastMessage), 0, 255, 0, width);
currX = floor(currX);
// console.log(currX);
}
function connectBtnClick() {
if (!port.opened()) {
port.open("Arduino", baudrate);
} else {
port.close();
}
}
2: LED Brightness
/*
* Week 11 Production (2)
*
* Outputs:
* - 5 - LED
*
*/
int ledPin = 5;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(ledPin, OUTPUT);
// Blink them so we can check the wiring
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
// start the handshake
while (Serial.available() <= 0) {
digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
Serial.println("0,0"); // send a starting message
delay(300); // wait 1/3 second
digitalWrite(LED_BUILTIN, LOW);
delay(50);
}
}
void loop() {
// wait for data from p5 before doing something
while (Serial.available()) {
digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
int brightness = Serial.parseInt();
if (Serial.read() == '\n') {
analogWrite(ledPin, brightness);
}
}
digitalWrite(LED_BUILTIN, LOW);
}
let port;
let baudrate = 9600;
// Show button to connect / disconnect
let showConnectButton = false;
function setup() {
createCanvas(640, 480);
textSize(20);
// Create the serial port
port = createSerial();
// If the user previously connected, reopen the same port
let usedPorts = usedSerialPorts();
if (usedPorts.length > 0) {
port.open(usedPorts[0], baudrate);
}
// any other ports can be opened via a dialog
if (showConnectButton) {
connectBtn = createButton('Connect to Arduino');
connectBtn.position(80, 350);
connectBtn.mousePressed(setupSerial);
}
}
// Show serial port connection dialog in response to action
function setupSerial() {
if (!port.opened()) {
port.open('Arduino', baudrate);
} else {
port.close();
}
}
function draw() {
background('white');
fill('black');
if (showConnectButton) {
// changes button label based on connection status
if (!port.opened()) {
connectBtn.html('Connect to Arduino');
} else {
connectBtn.html('Disconnect');
}
}
if (!port.opened()) {
text("Disconnected - press space to connect", 20, 30);
} else {
text("Connected - press space to disconnect", 20, 30);
// // Transmit brightness based on mouse position
mappedX = floor(map(mouseX, 0, width, 0, 255));
console.log(mappedX);
let sendToArduino = mappedX + "\n";
port.write(sendToArduino);
}
}
function keyPressed() {
if (key == " ") {
setupSerial();
}
}
3: Wind Gravity
/*
* Week 11 Production (3)
*
* Inputs:
* - A1 - 10k potentiometer connected to 5V and GND
*
* Outputs:
* - 5 - LED
*
*/
int potPin = A1;
int ledPin = 5;
int interval = 100;
int lastMessageTime = 0;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(potPin, INPUT);
pinMode(ledPin, OUTPUT);
// Blink them so we can check the wiring
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
// start the handshake
while (Serial.available() <= 0) {
digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
Serial.println("127"); // send a starting message
delay(300); // wait 1/3 second
digitalWrite(LED_BUILTIN, LOW);
delay(50);
}
}
void loop() {
// wait for data from p5 before doing something
while (Serial.available()) {
digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
// blink LED based on p5 data
int status = Serial.parseInt();
if (Serial.read() == '\n') {
digitalWrite(ledPin, status);
delay(10);
digitalWrite(ledPin, LOW);
}
if (lastMessageTime > interval) {
lastMessageTime = 0;
// send mapped potentiometer reading to p5
int potentiometer = analogRead(potPin);
int mappedPotValue = map(potentiometer, 0, 1023, 0, 255);
Serial.println(mappedPotValue);
// slight delay to stabilize the ADC:
delay(1);
}
else {
lastMessageTime++;
}
}
digitalWrite(LED_BUILTIN, LOW);
}
let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
// // Arduino
let port;
let connectBtn;
let baudrate = 9600;
let lastMessage = "";
let showConnectButton = false;
function setup() {
createCanvas(620, 400);
noFill();
position = createVector(width/2, 0);
velocity = createVector(0,0);
acceleration = createVector(0,0);
gravity = createVector(0, 0.5*mass);
wind = createVector(0,0);
// // Arduino
port = createSerial();
let usedPorts = usedSerialPorts();
if (usedPorts.length > 0) {
port.open(usedPorts[0], baudrate);
}
if (showConnectButton) {
connectBtn = createButton('Connect to Arduino');
connectBtn.position(80, 300);
connectBtn.mousePressed(setupSerial);
}
}
function draw() {
background(255);
applyForce(wind);
applyForce(gravity);
velocity.add(acceleration);
velocity.mult(drag);
position.add(velocity);
acceleration.mult(0);
ellipse(position.x,position.y,mass,mass);
if (position.y > height-mass/2) {
velocity.y *= -0.9; // A little dampening when hitting the bottom
position.y = height-mass/2;
flashLight();
}
// // Arduino
if (showConnectButton) {
if (!port.opened()) {
connectBtn.html('Connect to Arduino');
} else {
connectBtn.html('Disconnect');
}
}
fill('black');
if (!port.opened()) {
text("Disconnected", 20, 30);
} else {
text("Connected", 20, 30);
}
let str = port.readUntil("\n");
if (str.length > 0) {
// console.log(str);
lastMessage = str;
}
// Display the most recent message
text("Last message: " + lastMessage, 10, height - 20);
// // Convert received value to wind.x value
mappedPot = map(int(lastMessage), 0, 255, -1, 1);
wind.x = mappedPot;
let windSpeed = "Wind speed: " + wind.x
text(windSpeed.substring(0,20), 10, height - 5);
fill('white');
}
function applyForce(force){
// Newton's 2nd law: F = M * A
// or A = F / M
let f = p5.Vector.div(force, mass);
acceleration.add(f);
}
function keyPressed(){
if (keyCode==LEFT_ARROW){
wind.x=-1;
}
if (keyCode==RIGHT_ARROW){
wind.x=1;
}
if (key==' '){
mass=random(15,80);
position.y=-mass;
velocity.mult(0);
port.write("0\n"); // reset light
}
}
// // Arduino
function setupSerial() {
if (!port.opened()) {
port.open('Arduino', baudrate);
} else {
port.close();
}
}
function flashLight() {
if (port.opened()) {
port.write("1\n");
// port.write("0\n");
}
}