Since my midterm project was related to our campus, I wanted to work on something similar for the final project. I came up with the idea to create an interactive NYUAD campus explorer. I thought it would be a great project to showcase the beauty and resourcefulness of our campus.
My project consists of a physical 3D model of our campus and a p5.js sketch that provides information about individual buildings.
Afterward, the user sees the ID explanation page, where the narrator welcomes them to NYUAD and explains how the virtual tour works. I used the subscription logic from this source (https://editor.p5js.org/hk3863/sketches/OSSNouhkg ), but I’ve adjusted the texts and timings to fit my project.
An essential and creative aspect of this project is the NYU ID card, which is required to access buildings on the NYUAD campus. I’ve used an RFID sensor to replicate the ID card.
When the user clicks on the page, they’re taken to the instruction page, where they can press buttons for specific buildings to obtain information. Here’s the interesting part: after pressing a button, they must scan their ID card to access the information, just as they would when using their ID card to enter buildings.
My model includes five buttons, each linked to a page with information about a building: Campus Center, Dining Halls, Research Buildings, Residences, and the Arts Center. Each page includes photographs and buttons to navigate to the next or previous photo.
My Arduino code is sending two types of data. The first is the digital input from the buttons. I’ve created arrays so that when a specific button is pressed, the button number is sent to p5.js, which then triggers the relevant function about that particular building. The second data type comes from the RFID sensor. I watched several tutorials on YouTube to understand how RFID works. In my code, you’ll see that when the tag name of my card is detected by the RFID sensor, the sensor sends a “1” to p5.js, granting access to the information.
buttonPressed = i; // Store the pressed button index
}
}
}
}
#include <SPI.h>
#include <MFRC522.h>
// RFID Setup
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
// Button Setup
const int buttonPins[] = {2, 3, 4, 5, 6}; // Digital pins for buttons
const int numButtons = sizeof(buttonPins) / sizeof(buttonPins[0]);
bool lastButtonState[numButtons] = {0};
// RFID Access Card UID
const String AUTHORIZED_CARD_UID = "70 91 42 55";
bool isAuthorized = false;
int cardAccessStatus = 0;
int buttonPressed = -1;
void setup() {
// Initialize Serial Communication
Serial.begin(9600);
// Initialize RFID Reader
SPI.begin();
mfrc522.PCD_Init();
// Initialize Button Pins (Input Mode, assuming external pull-down resistors)
for (int i = 0; i < numButtons; i++) {
pinMode(buttonPins[i], INPUT);
}
}
void loop() {
// Check RFID Access
checkRFID();
// Process Button Presses
checkButtons();
// Send Combined Data
Serial.print(buttonPressed);
Serial.print(",");
Serial.println(cardAccessStatus);
// Reset button state only if no button is currently pressed
if (buttonPressed != -1) {
buttonPressed = -1;
}
delay(100); // Debounce delay
}
void checkRFID() {
// Look for new cards
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
// Show UID on Serial Monitor
String content = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
content.concat(String(mfrc522.uid.uidByte[i], HEX));
}
content.toUpperCase();
Serial.println("UID tag: " + content);
// Check if the card is authorized
if (content.substring(1) == AUTHORIZED_CARD_UID) {
isAuthorized = true;
cardAccessStatus = 1; // Set to 1 for authorized access
isAuthorized = false;
} else {
isAuthorized = false;
cardAccessStatus = 0; // Set to 0 for denied access
}
}
void checkButtons() {
for (int i = 0; i < numButtons; i++) {
// Button logic without pull-ups: HIGH = Button pressed
bool currentButtonState = digitalRead(buttonPins[i]) == HIGH;
if (currentButtonState != lastButtonState[i]) {
lastButtonState[i] = currentButtonState;
if (currentButtonState) {
buttonPressed = i; // Store the pressed button index
}
}
}
}
#include <SPI.h>
#include <MFRC522.h>
// RFID Setup
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
// Button Setup
const int buttonPins[] = {2, 3, 4, 5, 6}; // Digital pins for buttons
const int numButtons = sizeof(buttonPins) / sizeof(buttonPins[0]);
bool lastButtonState[numButtons] = {0};
// RFID Access Card UID
const String AUTHORIZED_CARD_UID = "70 91 42 55";
bool isAuthorized = false;
int cardAccessStatus = 0;
int buttonPressed = -1;
void setup() {
// Initialize Serial Communication
Serial.begin(9600);
// Initialize RFID Reader
SPI.begin();
mfrc522.PCD_Init();
// Initialize Button Pins (Input Mode, assuming external pull-down resistors)
for (int i = 0; i < numButtons; i++) {
pinMode(buttonPins[i], INPUT);
}
}
void loop() {
// Check RFID Access
checkRFID();
// Process Button Presses
checkButtons();
// Send Combined Data
Serial.print(buttonPressed);
Serial.print(",");
Serial.println(cardAccessStatus);
// Reset button state only if no button is currently pressed
if (buttonPressed != -1) {
buttonPressed = -1;
}
delay(100); // Debounce delay
}
void checkRFID() {
// Look for new cards
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
// Show UID on Serial Monitor
String content = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
content.concat(String(mfrc522.uid.uidByte[i], HEX));
}
content.toUpperCase();
Serial.println("UID tag: " + content);
// Check if the card is authorized
if (content.substring(1) == AUTHORIZED_CARD_UID) {
isAuthorized = true;
cardAccessStatus = 1; // Set to 1 for authorized access
isAuthorized = false;
} else {
isAuthorized = false;
cardAccessStatus = 0; // Set to 0 for denied access
}
}
void checkButtons() {
for (int i = 0; i < numButtons; i++) {
// Button logic without pull-ups: HIGH = Button pressed
bool currentButtonState = digitalRead(buttonPins[i]) == HIGH;
if (currentButtonState != lastButtonState[i]) {
lastButtonState[i] = currentButtonState;
if (currentButtonState) {
buttonPressed = i; // Store the pressed button index
}
}
}
}
Circuit
What I Am Proud Of
I am particularly proud of creating the physical 3D model. It was my first time using Illustrator and laser cutting, and it was exciting to see the results. Through this project, I learned how to use Illustrator to turn my ideas into reality. Additionally, I’m happy I tried using a new sensor (RFID), which wasn’t covered in class. I believe it aligns well with the project’s concept.
Further Improvements
Because I didn’t have enough time, I couldn’t paint the campus model. However, with more time, I believe I could have made this model much more beautiful. Additionally, I couldn’t include information about some buildings, such as D1, so I decided to combine D2 and D1.
Overall, I am satisfied with the project’s outcome and pleased that I tried several new things and learned so much from this experience.
IM Show
A lot of people came to see my project! I really enjoyed the experience of presenting my work to others. Through this, I was able to identify some bugs I hadn’t noticed before. People loved the 3D model of the campus I created. They suggested it could be used for Marhaba or campus tours.
My final project idea is to create a virtual tour of the NYUAD campus. This interactive tour will serve as a unique introduction to our campus for incoming students, new students, and faculty. The project will consist of three components: a physical 3D campus map, miniature figure, and an informational page featuring photographs on p5.js.
I will create a physical 3D model of our campus based on the campus map.
Using laser cutting, I will create several layers based on the map and then assemble them to form the buildings. Each building will have an RFID sensor at the entrance.
Users will utilize a miniature figure equipped with an RFID magnet sensor to interact with these buildings. When the user places the miniature figure in front of a building, the p5.js application will display photographs and information about that specific building.
The information page on p5.js will be designed as follows:
In summary, the functions of the Arduino and p5.js in this project are as follows:
– Arduino: Manages sensor inputs located in front of each building.
– p5.js: Displays photographs and information about the building when the sensors send data.
I clearly remember from one of the core classes I had taken that disability is made. For example, if you have visual problems, you can wear glasses. Now, you don’t have any disability. Thus, society has the power to change the discomfort we experience every day. By simply installing ramps instead of stairs, you are making someone undisabled. Everyone has some discomforts in life. Before, contacting someone was very difficult and time-consuming. So, someone invented the telephone to resolve that problem. Until then, people were not able to contact each other easily. I am trying to say that disability is not something special that cannot be resolved. Like the everyday problems we face today, disability can be solved with simple design. That is the power of design.
As the author says, disability inspires design; every single constraint we have in life can be a motivation to make something that can simplify our actions. I believe that design for disability is not a small market that should be ignored but rather a market that can inspire so many good designs for a larger population. As I have said before, we make disability. Every single design can actually solve disability. Just as ramps have replaced steps to aid those who cannot use stairs, various other design innovations can transform daily challenges into seamless activities. This transformative potential of design demonstrates its role not just in accommodating but in enabling and empowering individuals, thus reshaping our understanding of what it means to live with a disability.
Make something that uses only one sensor on arduino and makes the ellipse in p5 move on the horizontal axis, in the middle of the screen, and nothing on arduino is controlled by p5.
To complete this exercise, we built a simple circuit as illustrated below. We used the photocell to control the horizontal movement of the ball in p5.
As it is illustrated in the code for Arduino, most of it is similar to that of the one provided to the class. The things we changed are mostly done inside the void loop(). Since the Arduino is sending information to p5, we readjusted the code so that data is sent unidirectionally to p5: the value collected in A0 from the photocell is sent to p5.
Arudino Code
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
int leftLedPin = 2;
int rightLedPin = 5;
voidsetup(){
// Start serial communication so we can send data
// over the USB connection to our p5js sketch
Serial.begin(9600);
// We'll use the builtin LED as a status output.
// We can't use the serial monitor since the serial connection is
// used to communicate to p5js and only one application on the computer
// can use a serial port at once.
pinMode(LED_BUILTIN, OUTPUT);
// Outputs on these pins
pinMode(leftLedPin, OUTPUT);
pinMode(rightLedPin, OUTPUT);
// Blink them so we can check the wiring
digitalWrite(leftLedPin, HIGH);
digitalWrite(rightLedPin, HIGH);
delay(200);
digitalWrite(leftLedPin, LOW);
digitalWrite(rightLedPin, 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);
}
}
voidloop(){
// wait for data from p5 before doing something
int sensor = analogRead(A0);
delay(5);
Serial.println(sensor);
}
int leftLedPin = 2;
int rightLedPin = 5;
void setup() {
// Start serial communication so we can send data
// over the USB connection to our p5js sketch
Serial.begin(9600);
// We'll use the builtin LED as a status output.
// We can't use the serial monitor since the serial connection is
// used to communicate to p5js and only one application on the computer
// can use a serial port at once.
pinMode(LED_BUILTIN, OUTPUT);
// Outputs on these pins
pinMode(leftLedPin, OUTPUT);
pinMode(rightLedPin, OUTPUT);
// Blink them so we can check the wiring
digitalWrite(leftLedPin, HIGH);
digitalWrite(rightLedPin, HIGH);
delay(200);
digitalWrite(leftLedPin, LOW);
digitalWrite(rightLedPin, 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
int sensor = analogRead(A0);
delay(5);
Serial.println(sensor);
}
int leftLedPin = 2;
int rightLedPin = 5;
void setup() {
// Start serial communication so we can send data
// over the USB connection to our p5js sketch
Serial.begin(9600);
// We'll use the builtin LED as a status output.
// We can't use the serial monitor since the serial connection is
// used to communicate to p5js and only one application on the computer
// can use a serial port at once.
pinMode(LED_BUILTIN, OUTPUT);
// Outputs on these pins
pinMode(leftLedPin, OUTPUT);
pinMode(rightLedPin, OUTPUT);
// Blink them so we can check the wiring
digitalWrite(leftLedPin, HIGH);
digitalWrite(rightLedPin, HIGH);
delay(200);
digitalWrite(leftLedPin, LOW);
digitalWrite(rightLedPin, 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
int sensor = analogRead(A0);
delay(5);
Serial.println(sensor);
}
On p5, we drew an ellipse and initialized a variable ‘xposition’ that is used to move the horizontal position of the ball. Then under ‘if (data != null) {}’, we set the xposition = data where data refers to the value that is collected and sent from Arduino. This data is used to change the xposition of the ball in p5.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let rVal = 0;
let alpha = 255;
let xposition = 100;
functionsetup(){
createCanvas(640, 480);
textSize(18);
}
functiondraw(){
// one value from Arduino controls the background's red color
background(map(rVal, 0, 1023, 0, 255), 255, 200);
ellipse(xposition, height/2, 50, 50);
// the other value controls the text's transparency value
fill(255, 0, 255, map(alpha, 0, 1023, 0, 255));
if(!serialActive){
text("Press Space Bar to select Serial Port", 20, 30);
}else{
text("Connected", 20, 30);
// Print the current values
text('rVal = ' + str(rVal), 20, 50);
text('alpha = ' + str(alpha), 20, 70);
}
functionkeyPressed(){
if(key == " "){
// important to have in order to start the serial connection!!
setUpSerial();
}
}
// This function will be called by the web-serial library
// with each new *line* of data. The serial library reads
// the data until the newline and then gives it to us through
// this callback function
functionreadSerial(data){
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
if(data != null){
// make sure there is actually a message
// split the message
xposition = data;
}
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
let sendToArduino = left + "," + right + "\n";
writeSerial(sendToArduino);
}
let rVal = 0;
let alpha = 255;
let xposition = 100;
function setup() {
createCanvas(640, 480);
textSize(18);
}
function draw() {
// one value from Arduino controls the background's red color
background(map(rVal, 0, 1023, 0, 255), 255, 200);
ellipse(xposition, height/2, 50, 50);
// the other value controls the text's transparency value
fill(255, 0, 255, map(alpha, 0, 1023, 0, 255));
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
text("Connected", 20, 30);
// Print the current values
text('rVal = ' + str(rVal), 20, 50);
text('alpha = ' + str(alpha), 20, 70);
}
function keyPressed() {
if (key == " ") {
// important to have in order to start the serial connection!!
setUpSerial();
}
}
// This function will be called by the web-serial library
// with each new *line* of data. The serial library reads
// the data until the newline and then gives it to us through
// this callback function
function readSerial(data) {
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
if (data != null) {
// make sure there is actually a message
// split the message
xposition = data;
}
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
let sendToArduino = left + "," + right + "\n";
writeSerial(sendToArduino);
}
let rVal = 0;
let alpha = 255;
let xposition = 100;
function setup() {
createCanvas(640, 480);
textSize(18);
}
function draw() {
// one value from Arduino controls the background's red color
background(map(rVal, 0, 1023, 0, 255), 255, 200);
ellipse(xposition, height/2, 50, 50);
// the other value controls the text's transparency value
fill(255, 0, 255, map(alpha, 0, 1023, 0, 255));
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
text("Connected", 20, 30);
// Print the current values
text('rVal = ' + str(rVal), 20, 50);
text('alpha = ' + str(alpha), 20, 70);
}
function keyPressed() {
if (key == " ") {
// important to have in order to start the serial connection!!
setUpSerial();
}
}
// This function will be called by the web-serial library
// with each new *line* of data. The serial library reads
// the data until the newline and then gives it to us through
// this callback function
function readSerial(data) {
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
if (data != null) {
// make sure there is actually a message
// split the message
xposition = data;
}
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
let sendToArduino = left + "," + right + "\n";
writeSerial(sendToArduino);
}
EXERCISE 02: P5 TO ARDUINO COMMUNICATION
Make something that controls the LED brightness from p5.
For this exercise, we utilized the position of mouseX from p5 to control the brightness of the LED on Arduino. The circuit we made looks like this:
Here, Arduino receives information from p5 and changes the brightness of the LED. Under void loop(), we used the map function to convert the values to PWM range and used analogWrite to set the LED brightness according to the value received from p5.
ARDUINO CODE
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
int LEDpin = 3; // Ensure this pin supports PWM
voidsetup(){
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LEDpin, OUTPUT);
// Initial blink to confirm working setup
digitalWrite(LEDpin, HIGH);
delay(200);
digitalWrite(LEDpin, LOW);
// Wait for initial data before proceeding
while(Serial.available()<= 0){
digitalWrite(LED_BUILTIN, HIGH); // Blink LED to indicate waiting for connection
Serial.println("0,0"); // Send a starting message
delay(300);
digitalWrite(LED_BUILTIN, LOW);
delay(50);
}
}
voidloop(){
if(Serial.available()> 0){
digitalWrite(LED_BUILTIN, HIGH); // LED on while receiving data
int bright = Serial.parseInt();
bright = map(bright, 0, 640, 0, 255); // Adjust received value to PWM range
if(Serial.read() == '\n'){
analogWrite(LEDpin, bright); // Set LED brightness
}
digitalWrite(LED_BUILTIN, LOW); // Turn off status LED after handling data
Serial.println(0);
}
}
int LEDpin = 3; // Ensure this pin supports PWM
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LEDpin, OUTPUT);
// Initial blink to confirm working setup
digitalWrite(LEDpin, HIGH);
delay(200);
digitalWrite(LEDpin, LOW);
// Wait for initial data before proceeding
while (Serial.available() <= 0) {
digitalWrite(LED_BUILTIN, HIGH); // Blink LED to indicate waiting for connection
Serial.println("0,0"); // Send a starting message
delay(300);
digitalWrite(LED_BUILTIN, LOW);
delay(50);
}
}
void loop() {
if (Serial.available() > 0) {
digitalWrite(LED_BUILTIN, HIGH); // LED on while receiving data
int bright = Serial.parseInt();
bright = map(bright, 0, 640, 0, 255); // Adjust received value to PWM range
if (Serial.read() == '\n') {
analogWrite(LEDpin, bright); // Set LED brightness
}
digitalWrite(LED_BUILTIN, LOW); // Turn off status LED after handling data
Serial.println(0);
}
}
int LEDpin = 3; // Ensure this pin supports PWM
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LEDpin, OUTPUT);
// Initial blink to confirm working setup
digitalWrite(LEDpin, HIGH);
delay(200);
digitalWrite(LEDpin, LOW);
// Wait for initial data before proceeding
while (Serial.available() <= 0) {
digitalWrite(LED_BUILTIN, HIGH); // Blink LED to indicate waiting for connection
Serial.println("0,0"); // Send a starting message
delay(300);
digitalWrite(LED_BUILTIN, LOW);
delay(50);
}
}
void loop() {
if (Serial.available() > 0) {
digitalWrite(LED_BUILTIN, HIGH); // LED on while receiving data
int bright = Serial.parseInt();
bright = map(bright, 0, 640, 0, 255); // Adjust received value to PWM range
if (Serial.read() == '\n') {
analogWrite(LEDpin, bright); // Set LED brightness
}
digitalWrite(LED_BUILTIN, LOW); // Turn off status LED after handling data
Serial.println(0);
}
}
In p5, we used mouseX and its position on the canvas to control the brightness of the LED on Arduino. We initialized a variable LEDbright to 0 but then let it change according to the if statement. If mouseX <= width && mouseX >= 0 && mouseY <= height && mouseY >= 0 , then the variable LEDbright is mouseX and this data is then sent to Arduino which controls the brightness of the LED. However, if the condition is not satisfied, then the variable LEDbright remains 0. Simply put, the LED lights up brighter when the mouse is on the right side of the screen and dimmer when it is on the left side of the screen.
P5.JS CODE
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let LEDbright = 0;
functionsetup(){
createCanvas(640, 480);
textSize(18);
}
functiondraw(){
background(205);
// the other value controls the text's transparency value
fill(0)
if(!serialActive){
text("Press Space Bar to select Serial Port", 20, 30);
}else{
text("Connected", 20, 30);
}
// when clicked, digital LED will turn on,
// other analog write LED will have brightness corresponding to the height of the mouse when it is press. can be pressed and dragged for controlling brightness
// important to have in order to start the serial connection!!
setUpSerial();
}
}
functionreadSerial(data){
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
//send the posiiton of mouseY when clicked to control brightness
let sendToArduino = LEDbright + "\n";
writeSerial(sendToArduino);
}
let LEDbright = 0;
function setup() {
createCanvas(640, 480);
textSize(18);
}
function draw() {
background(205);
// the other value controls the text's transparency value
fill(0)
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
text("Connected", 20, 30);
}
// when clicked, digital LED will turn on,
// other analog write LED will have brightness corresponding to the height of the mouse when it is press. can be pressed and dragged for controlling brightness
if (mouseX <= width && mouseX >= 0 && mouseY <= height && mouseY >= 0) {
LEDbright = mouseX;
} else {
LEDbright = 0;
}
}
function keyPressed() {
if (key == " ") {
// important to have in order to start the serial connection!!
setUpSerial();
}
}
function readSerial(data) {
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
//send the posiiton of mouseY when clicked to control brightness
let sendToArduino = LEDbright + "\n";
writeSerial(sendToArduino);
}
let LEDbright = 0;
function setup() {
createCanvas(640, 480);
textSize(18);
}
function draw() {
background(205);
// the other value controls the text's transparency value
fill(0)
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
text("Connected", 20, 30);
}
// when clicked, digital LED will turn on,
// other analog write LED will have brightness corresponding to the height of the mouse when it is press. can be pressed and dragged for controlling brightness
if (mouseX <= width && mouseX >= 0 && mouseY <= height && mouseY >= 0) {
LEDbright = mouseX;
} else {
LEDbright = 0;
}
}
function keyPressed() {
if (key == " ") {
// important to have in order to start the serial connection!!
setUpSerial();
}
}
function readSerial(data) {
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
//send the posiiton of mouseY when clicked to control brightness
let sendToArduino = LEDbright + "\n";
writeSerial(sendToArduino);
}
EXERCISE 03: BI-DIRECTIONAL COMMUNICATION
Take the gravity wind example and make it so:
every time the ball bounces one led lights up and then turns off,
and you can control the wind from one analog sensor
To complete this assignment, we used a potentiometer as an input to control wind and an LED as an output controlled by the bouncing ball in p5.js.
P5.JS CODE
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let light = 0;
functionsetup(){
createCanvas(640, 360);
noFill();
position = createVector(width/2, 0);
velocity = createVector(0,0);
acceleration = createVector(0,0);
gravity = createVector(0, 0.5*mass);
wind = createVector(0,0);
}
functiondraw(){
background(255);
applyForce(wind);
applyForce(gravity);
velocity.add(acceleration);
velocity.mult(drag);
position.add(velocity);
acceleration.mult(0);
fill('black')
if(!serialActive){
text("Press Space Bar to select Serial Port", 20, 30);
}else{
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;
light=1
}
else{
light=0
}
}
}
functionapplyForce(force){
// Newton's 2nd law: F = M * A
// or A = F / M
let f = p5.Vector.div(force, mass);
acceleration.add(f);
}
functionkeyPressed(){
if(key == " "){
// important to have in order to start the serial connection!!
setUpSerial();
}
}
functionreadSerial(data){
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
if(data != null){
// make sure there is actually a message
// split the message
let fromArduino = split(trim(data), ",");
// if the right length, then proceed
if(fromArduino.length == 1){
// only store values here
// do everything with those values in the main draw loop
// We take the string we get from Arduino and explicitly
// convert it to a number by using int()
// e.g. "103" becomes 103
let sensorValue = int(fromArduino[0]);
wind.x = map(sensorValue, 0, 1023, -1, 1);
}
}
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
let sendToArduino = light + "\n";
writeSerial(sendToArduino);
}
let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let light = 0;
function setup() {
createCanvas(640, 360);
noFill();
position = createVector(width/2, 0);
velocity = createVector(0,0);
acceleration = createVector(0,0);
gravity = createVector(0, 0.5*mass);
wind = createVector(0,0);
}
function draw() {
background(255);
applyForce(wind);
applyForce(gravity);
velocity.add(acceleration);
velocity.mult(drag);
position.add(velocity);
acceleration.mult(0);
fill('black')
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
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;
light=1
}
else{
light=0
}
}
}
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 (key == " ") {
// important to have in order to start the serial connection!!
setUpSerial();
}
}
function readSerial(data) {
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
if (data != null) {
// make sure there is actually a message
// split the message
let fromArduino = split(trim(data), ",");
// if the right length, then proceed
if (fromArduino.length == 1) {
// only store values here
// do everything with those values in the main draw loop
// We take the string we get from Arduino and explicitly
// convert it to a number by using int()
// e.g. "103" becomes 103
let sensorValue = int(fromArduino[0]);
wind.x = map(sensorValue, 0, 1023, -1, 1);
}
}
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
let sendToArduino = light + "\n";
writeSerial(sendToArduino);
}
let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let light = 0;
function setup() {
createCanvas(640, 360);
noFill();
position = createVector(width/2, 0);
velocity = createVector(0,0);
acceleration = createVector(0,0);
gravity = createVector(0, 0.5*mass);
wind = createVector(0,0);
}
function draw() {
background(255);
applyForce(wind);
applyForce(gravity);
velocity.add(acceleration);
velocity.mult(drag);
position.add(velocity);
acceleration.mult(0);
fill('black')
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
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;
light=1
}
else{
light=0
}
}
}
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 (key == " ") {
// important to have in order to start the serial connection!!
setUpSerial();
}
}
function readSerial(data) {
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
if (data != null) {
// make sure there is actually a message
// split the message
let fromArduino = split(trim(data), ",");
// if the right length, then proceed
if (fromArduino.length == 1) {
// only store values here
// do everything with those values in the main draw loop
// We take the string we get from Arduino and explicitly
// convert it to a number by using int()
// e.g. "103" becomes 103
let sensorValue = int(fromArduino[0]);
wind.x = map(sensorValue, 0, 1023, -1, 1);
}
}
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
let sendToArduino = light + "\n";
writeSerial(sendToArduino);
}
ARDUINO CODE
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
int LEDpin = 2;
int wind = A0;
voidsetup(){
// Start serial communication so we can send data
// over the USB connection to our p5js sketch
Serial.begin(9600);
// We'll use the builtin LED as a status output.
// We can't use the serial monitor since the serial connection is
// used to communicate to p5js and only one application on the computer
// can use a serial port at once.
pinMode(LED_BUILTIN, OUTPUT);
// Outputs on these pins
pinMode(LEDpin, OUTPUT);
pinMode(wind, INPUT);
// 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
}
}
voidloop(){
// wait for data from p5 before doing something
while(Serial.available()){
digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
int light = Serial.parseInt();
if(Serial.read() == '\n'){
digitalWrite(LEDpin, light);
int sensor = analogRead(A0);
delay(5);
Serial.println(sensor);
}
}
digitalWrite(LED_BUILTIN, LOW);
}
int LEDpin = 2;
int wind = A0;
void setup() {
// Start serial communication so we can send data
// over the USB connection to our p5js sketch
Serial.begin(9600);
// We'll use the builtin LED as a status output.
// We can't use the serial monitor since the serial connection is
// used to communicate to p5js and only one application on the computer
// can use a serial port at once.
pinMode(LED_BUILTIN, OUTPUT);
// Outputs on these pins
pinMode(LEDpin, OUTPUT);
pinMode(wind, INPUT);
// 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
}
}
void loop() {
// wait for data from p5 before doing something
while (Serial.available()) {
digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
int light = Serial.parseInt();
if (Serial.read() == '\n') {
digitalWrite(LEDpin, light);
int sensor = analogRead(A0);
delay(5);
Serial.println(sensor);
}
}
digitalWrite(LED_BUILTIN, LOW);
}
int LEDpin = 2;
int wind = A0;
void setup() {
// Start serial communication so we can send data
// over the USB connection to our p5js sketch
Serial.begin(9600);
// We'll use the builtin LED as a status output.
// We can't use the serial monitor since the serial connection is
// used to communicate to p5js and only one application on the computer
// can use a serial port at once.
pinMode(LED_BUILTIN, OUTPUT);
// Outputs on these pins
pinMode(LEDpin, OUTPUT);
pinMode(wind, INPUT);
// 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
}
}
void loop() {
// wait for data from p5 before doing something
while (Serial.available()) {
digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
int light = Serial.parseInt();
if (Serial.read() == '\n') {
digitalWrite(LEDpin, light);
int sensor = analogRead(A0);
delay(5);
Serial.println(sensor);
}
}
digitalWrite(LED_BUILTIN, LOW);
}
To briefly explain this code, every time the ball hits the ground, the variable ‘light’ is set to 1. If this is not the case, ‘light’ is set to 0.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if(!serialActive){
text("Press Space Bar to select Serial Port", 20, 30);
}else{
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;
light=1
}
else{
light=0
}
}
}
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
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;
light=1
}
else{
light=0
}
}
}
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
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;
light=1
}
else{
light=0
}
}
}
Then, p5.js sends the value of ‘light’ to the Arduino.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let sendToArduino = light + "\n";
writeSerial(sendToArduino);
let sendToArduino = light + "\n";
writeSerial(sendToArduino);
let sendToArduino = light + "\n";
writeSerial(sendToArduino);
When the Arduino receives the light value from p5.js, it turns on if the value is 1 and turns off if the value equals 0.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
int light = Serial.parseInt();
if(Serial.read() == '\n'){
digitalWrite(LEDpin, light);
int light = Serial.parseInt();
if (Serial.read() == '\n') {
digitalWrite(LEDpin, light);
int light = Serial.parseInt();
if (Serial.read() == '\n') {
digitalWrite(LEDpin, light);
To control the wind value, if the length of the data sensed by the Arduino is equal to 1, p5.js receives the data value of the potentiometer. We then use the map function to convert the analog input value from 0 to 1023 to a range of -1 to 1.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if(data != null){
// make sure there is actually a message
// split the message
let fromArduino = split(trim(data), ",");
// if the right length, then proceed
if(fromArduino.length == 1){
// only store values here
// do everything with those values in the main draw loop
// We take the string we get from Arduino and explicitly
// convert it to a number by using int()
// e.g. "103" becomes 103
let sensorValue = int(fromArduino[0]);
wind.x = map(sensorValue, 0, 1023, -1, 1);
}
}
if (data != null) {
// make sure there is actually a message
// split the message
let fromArduino = split(trim(data), ",");
// if the right length, then proceed
if (fromArduino.length == 1) {
// only store values here
// do everything with those values in the main draw loop
// We take the string we get from Arduino and explicitly
// convert it to a number by using int()
// e.g. "103" becomes 103
let sensorValue = int(fromArduino[0]);
wind.x = map(sensorValue, 0, 1023, -1, 1);
}
}
if (data != null) {
// make sure there is actually a message
// split the message
let fromArduino = split(trim(data), ",");
// if the right length, then proceed
if (fromArduino.length == 1) {
// only store values here
// do everything with those values in the main draw loop
// We take the string we get from Arduino and explicitly
// convert it to a number by using int()
// e.g. "103" becomes 103
let sensorValue = int(fromArduino[0]);
wind.x = map(sensorValue, 0, 1023, -1, 1);
}
}
My goal is to create an interesting way to explore NYUAD. This project will combine physical interactivity with digital technology, providing a unique and engaging way to learn about our campus.
How It works
I am planning to create a tangible, interactive experience with a physical 3D model of the NYUAD campus, where each building is equipped with sensors. Additionally, I will use a small model of a person outfitted with a compatible sensor. When this person model is placed near or inside one of the buildings on the campus model, the sensors will detect its proximity or contact. The Arduino will then send a signal to a computer system, indicating which building the person model has been placed in. This signal will trigger a p5.js application to display specific information about that building on a screen. The displayed information can include textual descriptions, historical facts, photographs, and potentially other multimedia elements.
Purpose and Benefits
When I was accepted to NYUAD, I was curious about the campus buildings, but I could not find much information or photographs of our campus on the internet. Mainly, I wanted to create this project as a unique way for our students, faculty, and prospective students to learn about our campus. Also, this tool is invaluable for orientation programs, helping new students and staff familiarize themselves quickly and effectively with the campus.
Main Challenges
Currently, I am not sure which sensor to use in both the buildings and the miniature person.
I have always imagined future technology, but the way the author describes the future was very eye-opening. I have always thought of a world with smart technology and screens but never considered that our hands could be essential tools for the future. I agree with the author that we perceive the world through touch. The hand is a tool used every day, helping us navigate our lives. However, today’s reading made me realize that the tactile experience is often overlooked when we use our everyday devices.
As children, we learned about different objects in this world through our tactile sense. This experience of learning through touching and using our hands and bodies has shaped who we are today. Thanks to these experiences, I know how to hold a cup, how to throw a ball, and I am familiar with the feelings of sand, rocks, and water. However, if the children of the future start learning things only through ‘pictures under glass,’ they will not be as well-rounded as we are now. They will miss out on knowing how wonderful the world is.
As the author emphasizes the importance of hands, I truly think that this overlooked issue should be addressed in the future with all possible technological advancements. I want to live in a world where my hands are useful. I want to live in a world where technology offers more than just ‘pictures under glass,’ and where I can truly feel the world.
When we were young, we were taught to sing and play instruments to a song called “떴다 떴다 비행기”. This song is about airplanes and with the introduction to airplanes through this song, we learn more about airplanes and dream of riding it one day. Furthermore, when we played as elementary students in the playground, we always sang this song and looked up to the sky to find some airplanes. Now, as older students, playing this song on our instrument reminds us of our childhood in South Korea.
Circuit
For digital, we used 3 buttons. Each button is connected to the Ground, a 330 ohm resistor and digital input (2, 3, 4).
For analog, we used a potentiometer and a speaker. The speaker is connected to the Ground and analog input (~9). The potentiometer is connected to 5V, A0, and the Ground.
Code
We have created a code so that when a button is pressed, the corresponding note is played with a frequency that can be altered up or down by the potentiometer. The constants BASE_NOTE_C4, BASE_NOTE_D4, and BASE_NOTE_E4 are defined at the top of the sketch. To simplify the code, we have used the INPUT_PULLUP function in the ‘setup’ function, which means that the button pin will read HIGH when unpressed and LOW when pressed.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
voidsetup(){
for(int i = 0; i < 3; i++){
pinMode(buttonPins[i], INPUT_PULLUP); // Setup as pull-up to simplify wiring
}
pinMode(buzzerPin, OUTPUT);
}
void setup() {
for (int i = 0; i < 3; i++) {
pinMode(buttonPins[i], INPUT_PULLUP); // Setup as pull-up to simplify wiring
}
pinMode(buzzerPin, OUTPUT);
}
void setup() {
for (int i = 0; i < 3; i++) {
pinMode(buttonPins[i], INPUT_PULLUP); // Setup as pull-up to simplify wiring
}
pinMode(buzzerPin, OUTPUT);
}
In the main program loop, the potentiometer’s value is read from ‘potPin’ and mapped from its reading rand (0 to 1023) to a frequency adjustment range of -100 to +100 Hz. The loop checks each button in the buttonPins array to see if it’s pressed (reads LOW due to the pull-up resistor). If a button is pressed, the function playAdjustedTone() is called.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
voidloop(){
int frequencyAdjustment = analogRead(potPin); // Read the potentiometer value
frequencyAdjustment = map(frequencyAdjustment, 0, 1023, -100, 100); // Map the pot value to a frequency range adjustment
for(int i = 0; i <3; i++){
if(digitalRead(buttonPins[i]) == LOW){// Check if button is pressed
playAdjustedTone(i, frequencyAdjustment);
}
}
}
void loop() {
int frequencyAdjustment = analogRead(potPin); // Read the potentiometer value
frequencyAdjustment = map(frequencyAdjustment, 0, 1023, -100, 100); // Map the pot value to a frequency range adjustment
for (int i = 0; i < 3; i++) {
if (digitalRead(buttonPins[i]) == LOW) { // Check if button is pressed
playAdjustedTone(i, frequencyAdjustment);
}
}
}
void loop() {
int frequencyAdjustment = analogRead(potPin); // Read the potentiometer value
frequencyAdjustment = map(frequencyAdjustment, 0, 1023, -100, 100); // Map the pot value to a frequency range adjustment
for (int i = 0; i < 3; i++) {
if (digitalRead(buttonPins[i]) == LOW) { // Check if button is pressed
playAdjustedTone(i, frequencyAdjustment);
}
}
}
We wanted to use the potentiometer to adjust the tone. So we have written the playAdjustedTone() function. It calculates the adjusted frequency for the selected note by adding the frequency adjustment value from the potentiometer to the base frequency of the note. It then uses tone(buzzerPin, adjustedFrequency) to play the adjusted note for 100 milliseconds.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
voidplayAdjustedTone(int noteIndex, int adjustment){
int baseFrequencies[] = {BASE_NOTE_C4, BASE_NOTE_D4, BASE_NOTE_E4}; // Base frequencies for C, D, E
int adjustedFrequency = baseFrequencies[noteIndex] + adjustment; // Adjust the frequency based on potentiometer
tone(buzzerPin, adjustedFrequency); // Play the adjusted note
delay(100); // Duration of note
noTone(buzzerPin); // Stop the tone
}
void playAdjustedTone(int noteIndex, int adjustment) {
int baseFrequencies[] = {BASE_NOTE_C4, BASE_NOTE_D4, BASE_NOTE_E4}; // Base frequencies for C, D, E
int adjustedFrequency = baseFrequencies[noteIndex] + adjustment; // Adjust the frequency based on potentiometer
tone(buzzerPin, adjustedFrequency); // Play the adjusted note
delay(100); // Duration of note
noTone(buzzerPin); // Stop the tone
}
void playAdjustedTone(int noteIndex, int adjustment) {
int baseFrequencies[] = {BASE_NOTE_C4, BASE_NOTE_D4, BASE_NOTE_E4}; // Base frequencies for C, D, E
int adjustedFrequency = baseFrequencies[noteIndex] + adjustment; // Adjust the frequency based on potentiometer
tone(buzzerPin, adjustedFrequency); // Play the adjusted note
delay(100); // Duration of note
noTone(buzzerPin); // Stop the tone
}
After playing the note, noTone(buzzerPin) stops the buzzer.
Here is the full version of our code:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Define frequencies for musical notes C, D, E
#define BASE_NOTE_C4 261
#define BASE_NOTE_D4 294
#define BASE_NOTE_E4 329
// Define pin connections
const int buzzerPin = 9;
const int potPin = A0;
const int buttonPins[] = {2, 3, 4}; // Buttons for C, D, E notes
voidsetup(){
for(int i = 0; i <3; i++){
pinMode(buttonPins[i], INPUT_PULLUP); // Setup as pull-up to simplify wiring
}
pinMode(buzzerPin, OUTPUT);
}
voidloop(){
int frequencyAdjustment = analogRead(potPin); // Read the potentiometer value
frequencyAdjustment = map(frequencyAdjustment, 0, 1023, -100, 100); // Map the pot value to a frequency range adjustment
for(int i = 0; i <3; i++){
if(digitalRead(buttonPins[i]) == LOW){// Check if button is pressed
playAdjustedTone(i, frequencyAdjustment);
}
}
}
voidplayAdjustedTone(int noteIndex, int adjustment){
int baseFrequencies[] = {BASE_NOTE_C4, BASE_NOTE_D4, BASE_NOTE_E4}; // Base frequencies for C, D, E
int adjustedFrequency = baseFrequencies[noteIndex] + adjustment; // Adjust the frequency based on potentiometer
tone(buzzerPin, adjustedFrequency); // Play the adjusted note
delay(100); // Duration of note
noTone(buzzerPin); // Stop the tone
}
// Define frequencies for musical notes C, D, E
#define BASE_NOTE_C4 261
#define BASE_NOTE_D4 294
#define BASE_NOTE_E4 329
// Define pin connections
const int buzzerPin = 9;
const int potPin = A0;
const int buttonPins[] = {2, 3, 4}; // Buttons for C, D, E notes
void setup() {
for (int i = 0; i < 3; i++) {
pinMode(buttonPins[i], INPUT_PULLUP); // Setup as pull-up to simplify wiring
}
pinMode(buzzerPin, OUTPUT);
}
void loop() {
int frequencyAdjustment = analogRead(potPin); // Read the potentiometer value
frequencyAdjustment = map(frequencyAdjustment, 0, 1023, -100, 100); // Map the pot value to a frequency range adjustment
for (int i = 0; i < 3; i++) {
if (digitalRead(buttonPins[i]) == LOW) { // Check if button is pressed
playAdjustedTone(i, frequencyAdjustment);
}
}
}
void playAdjustedTone(int noteIndex, int adjustment) {
int baseFrequencies[] = {BASE_NOTE_C4, BASE_NOTE_D4, BASE_NOTE_E4}; // Base frequencies for C, D, E
int adjustedFrequency = baseFrequencies[noteIndex] + adjustment; // Adjust the frequency based on potentiometer
tone(buzzerPin, adjustedFrequency); // Play the adjusted note
delay(100); // Duration of note
noTone(buzzerPin); // Stop the tone
}
// Define frequencies for musical notes C, D, E
#define BASE_NOTE_C4 261
#define BASE_NOTE_D4 294
#define BASE_NOTE_E4 329
// Define pin connections
const int buzzerPin = 9;
const int potPin = A0;
const int buttonPins[] = {2, 3, 4}; // Buttons for C, D, E notes
void setup() {
for (int i = 0; i < 3; i++) {
pinMode(buttonPins[i], INPUT_PULLUP); // Setup as pull-up to simplify wiring
}
pinMode(buzzerPin, OUTPUT);
}
void loop() {
int frequencyAdjustment = analogRead(potPin); // Read the potentiometer value
frequencyAdjustment = map(frequencyAdjustment, 0, 1023, -100, 100); // Map the pot value to a frequency range adjustment
for (int i = 0; i < 3; i++) {
if (digitalRead(buttonPins[i]) == LOW) { // Check if button is pressed
playAdjustedTone(i, frequencyAdjustment);
}
}
}
void playAdjustedTone(int noteIndex, int adjustment) {
int baseFrequencies[] = {BASE_NOTE_C4, BASE_NOTE_D4, BASE_NOTE_E4}; // Base frequencies for C, D, E
int adjustedFrequency = baseFrequencies[noteIndex] + adjustment; // Adjust the frequency based on potentiometer
tone(buzzerPin, adjustedFrequency); // Play the adjusted note
delay(100); // Duration of note
noTone(buzzerPin); // Stop the tone
}
Reflection
For improvement, we would like to add more buttons so that we can play more musical notes. In this way, the range of songs we can play on the instrument would widen and it would be more entertaining to play along on the instrument. Also, we tried to change the volume of the sound through the potentiometer but was unsuccessful at it. Therefore, for this assignment, we utilized the potentiometer to control the tone instead. In the future, however, we would like to learn and utilize volume control using the potentiometer.
After completing my project, I began contemplating a creative concept for it. It occurred to me that if I had a child, I would use this project as a toy to help them quickly learn colors. Consequently, I decided to name this project the “Interactive Color Toy.” Children can use it as a toy, pressing a button to cycle through three colors: red, yellow, and green. Additionally, they can adjust the LED’s brightness using a potentiometer. By pressing the button and changing the brightness, children could easily learn colors through tactile experiences, especially if parents help by naming the colors that appear when the button is pressed.
Circuit
My circuit consists of the following elements:
– Arduino board (e.g., Arduino Uno)
– Potentiometer
– Push button switch
– LED
– Resistors
– Breadboard
– Jumper wires
In this circuit, a potentiometer is connected to an analog input pin of the Arduino, allowing it to read varying voltage levels. A push button is connected to a digital input pin, enabling the Arduino to detect button presses. Three digital output pins are connected to the red, green, and yellow pins of the LED, respectively. By adjusting the potentiometer, users control the brightness of the LED colors, while pressing the button cycles through the available colors.
Code
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Pins
constint POTENTIOMETER_PIN = A0; // Analog input pin for potentiometer
constint BUTTON_PIN = 2; // Digital input pin for push button
constint RED = 5; // Digital output pin for RGB LED (red)
constint GREEN = 6; // Digital output pin for RGB LED (green)
constint YELLOW = 9; // Digital output pin for RGB LED (yellow)
// Variables
int potentiometerValue = 0; // Potentiometer value
int brightness = map(potentiometerValue, 0, 1023, 0, 255);
// Set the LED color based on the current color index
switch(colorIndex){
case 0: // Red
analogWrite(RED, brightness);
analogWrite(GREEN, 0);
analogWrite(YELLOW, 0);
break;
case 1: // Green
analogWrite(RED, 0);
analogWrite(GREEN, brightness);
analogWrite(YELLOW, 0);
break;
case 2: // Yellow
analogWrite(RED, 0);
analogWrite(GREEN, 0);
analogWrite(YELLOW, brightness);
break;
}
// Check button state
if(digitalRead(BUTTON_PIN) == LOW){
if(!buttonState){
// Toggle color index
colorIndex = (colorIndex + 1) % 3;
buttonState = true;
delay(200);
}
}else{
buttonState = false;
}
}
// Pins
const int POTENTIOMETER_PIN = A0; // Analog input pin for potentiometer
const int BUTTON_PIN = 2; // Digital input pin for push button
const int RED = 5; // Digital output pin for RGB LED (red)
const int GREEN = 6; // Digital output pin for RGB LED (green)
const int YELLOW = 9; // Digital output pin for RGB LED (yellow)
// Variables
int potentiometerValue = 0; // Potentiometer value
bool buttonState = false; // Button state
int colorIndex = 0; // Index of current color
void setup() {
pinMode(POTENTIOMETER_PIN, INPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(YELLOW, OUTPUT);
}
void loop() {
potentiometerValue = analogRead(POTENTIOMETER_PIN);
// Map potentiometer value to LED brightness
int brightness = map(potentiometerValue, 0, 1023, 0, 255);
// Set the LED color based on the current color index
switch (colorIndex) {
case 0: // Red
analogWrite(RED, brightness);
analogWrite(GREEN, 0);
analogWrite(YELLOW, 0);
break;
case 1: // Green
analogWrite(RED, 0);
analogWrite(GREEN, brightness);
analogWrite(YELLOW, 0);
break;
case 2: // Yellow
analogWrite(RED, 0);
analogWrite(GREEN, 0);
analogWrite(YELLOW, brightness);
break;
}
// Check button state
if (digitalRead(BUTTON_PIN) == LOW) {
if (!buttonState) {
// Toggle color index
colorIndex = (colorIndex + 1) % 3;
buttonState = true;
delay(200);
}
} else {
buttonState = false;
}
}
// Pins
const int POTENTIOMETER_PIN = A0; // Analog input pin for potentiometer
const int BUTTON_PIN = 2; // Digital input pin for push button
const int RED = 5; // Digital output pin for RGB LED (red)
const int GREEN = 6; // Digital output pin for RGB LED (green)
const int YELLOW = 9; // Digital output pin for RGB LED (yellow)
// Variables
int potentiometerValue = 0; // Potentiometer value
bool buttonState = false; // Button state
int colorIndex = 0; // Index of current color
void setup() {
pinMode(POTENTIOMETER_PIN, INPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(YELLOW, OUTPUT);
}
void loop() {
potentiometerValue = analogRead(POTENTIOMETER_PIN);
// Map potentiometer value to LED brightness
int brightness = map(potentiometerValue, 0, 1023, 0, 255);
// Set the LED color based on the current color index
switch (colorIndex) {
case 0: // Red
analogWrite(RED, brightness);
analogWrite(GREEN, 0);
analogWrite(YELLOW, 0);
break;
case 1: // Green
analogWrite(RED, 0);
analogWrite(GREEN, brightness);
analogWrite(YELLOW, 0);
break;
case 2: // Yellow
analogWrite(RED, 0);
analogWrite(GREEN, 0);
analogWrite(YELLOW, brightness);
break;
}
// Check button state
if (digitalRead(BUTTON_PIN) == LOW) {
if (!buttonState) {
// Toggle color index
colorIndex = (colorIndex + 1) % 3;
buttonState = true;
delay(200);
}
} else {
buttonState = false;
}
}
This is my code. The analogRead function reads the value from the potentiometer, which is then mapped to control the brightness of the LED colors. The switch statement selects the appropriate color based on the current color index, and the digitalWrite function sets the brightness of the corresponding LED pins accordingly. When the button is pressed, the color index is incremented to cycle through the available colors.
Improvements and Overview
Overall, I enjoyed this assignment, particularly the aspect of controlling outputs using different physical inputs. The most challenging part was figuring out how the current moved through the circuit. However, I was able to easily determine the correct way to connect all the components. As a further improvement, I considered expanding the color palette by using a full RGB LED instead of individual colors. This would allow for a wider range of colors and more creative possibilities.
This reading was particularly informative, offering a wide array of projects within the field of physical computing. Previously, I had never imagined that such diverse and innovative projects were feasible when I first began my journey in this field. Particularly, I was fascinated by the idea of the theremin. This was a project I had wanted to work on when I was enrolled in another class last semester. However, due to my limited knowledge at the time, I couldn’t bring my ideas to reality. Now, equipped with the skills I’ve acquired from our recent classes, I feel confident and excited about the possibility of making this project a reality. The potential to combine electronic components with musical creativity truly captures the essence of what makes physical computing so exciting.
Making Interactive Art: Set the Stage, Then Shut Up and Listen
I really liked the directness and clarity in the title of the article. It reflects a fundamental truth about design: designers are communicators, not merely speakers. They show their thoughts through their creations. As the article discusses, Interactive Art goes beyond traditional boundaries by transforming viewers into active participants. This dynamic completes the artwork, creating a shared authorship between the creator and the audience. My experience last summer in a South Korean museum demonstrated this concept. There, I saw an interactive installation where visitors could draw animals and scan them to integrate their creations into the larger display with a pre-created background. This not only made the artwork dynamic but also personal, as each visitor’s contribution became central to the artistic narrative. It was a vivid demonstration of the profound connection that interactive art can forge, drawing beauty from the synergy between the artist’s vision and the audience’s involvement.
There is a moment where imagination sparks innovation. For me, that moment took me back to the muddy adventures of my childhood. Picture this: a young kid, covered in mud, going back home. It is necessary to turn on the lights without adding to the crime scene. And from this muddy dilemma, an idea was born—a switch that doesn’t need a clean hand but just a simple step.
Progress
I made a simple circuit out of these components: 5V – jumper wire – resistor – jumper wire – LED – Ground. It was easy to make the circuit, however, the key was to create a gap in the circuit, hidden beneath the carpet. This gap was placed between the resistor and the jumper wires, completing the circuit only when pressure was applied. Stepping on the carpet would bridge this gap, lighting up the LED. However, this design came with limitations. The switch was only one-time usable. After activation, the gap in the circuit needed manual resetting for the next use.
Reflection
I enjoyed doing this assignment. Of course, the idea that I came up was very simple. However, I could learn from this assignment that creativity comes from everyday problems, and perhaps the solution could be very simple.