Conception and Design:
I’m someone who likes studying in intervals, which greatly allows for my productivity to stay high for longer in contrast to studying for hours and hours which greatly declines faster. Below is a graph that shows the difference between studying with breaks vs without.
This graph shows the productivity of a study session with and without breaks. As you can see, after 5 hrs, the one who took breaks in between had higher productivity for longer. That’s why I always study in intervals. However, I use my phone as a timer. I do 30 minutes of focus work and then take a 5-10 minute break after each 30 min interval. After 30 min, though, since I use my phone as a timer, I have to go on my phone and turn off the alarm. Oftentimes when after turning my alarm off since my phone is already in my hands, I get distracted by it, and my breaks go from 5 minutes to 10 minutes to 20 minutes, and so on and so forth. This ultimately ruins the point of studying in intervals, as my productivity declines anyway.
The goal of my Project:
My project proposes a focus study environment that encourages focused work. This is done by eliminating the risk of getting distracted by cell phones, as it’s a self-sufficient circuit that only needs the user to interact with it to work. It promotes the idea of “interval studying.” The circuit uses LED lights around the user’s study area to create an enjoyable and entertaining study session while adding to the ambiance. Often times when I study, I listen to music, so this circuit allows you to upload music the lights will react to the music, and the brightness changes based on the amplitude of the song and changes colors every 10 seconds. This adds to the enjoyability of studying as it creates an environment that interacts with the music used to study. Then after the study session is over, a new Neo pixel system is used for however long the user wants to study. The first mode, where the lights are reacting to the music, makes all the LEDs one color at a time, and when the colors change, all of the LEDs change to the same color as well. However, when the study session is over, the alarm goes off. The Neopixel lights turn to random RGB colors and react to the amplitude of the alarm. To turn this system and alarm off, the user must put his/her hand anywhere from <5cm from the ultrasonic, sonic sensor on the study buddy’s left side. Then once the system is turned off, to restart the study session mode, the user must place their hand 10cm<x<30cm away from the sensor. This will reset the system back to the first mode, the study mode. This project is supposed to promote interval studying while limiting external distractions as much as possible. The way my project is set up in a scaled-down version of how the system would work. The study buddy creates a study-inducive environment meaning that the lights would most likely be hung up in the room where the user is studying and not in the box I fabricated. However, the user could use it in the box format, too if they liked because I know that some people believe that the “cublic-esque” feeling adds to their focus as it essentially traps them in a new space. My decisions for the project are justified by what I would like in a study buddy. I like to study music, so I incorporated that into my project.I also believe that light interactivity with music is super cool, so I included that. I also thought using the ultrasonic was a new way of adding interactivity vs. pushing a button. So I used that hand motion as the trigger for functions rather than a button.
Fabrication and Production:
The most significant step in my production process was looking back at recitation 7 and the code. This opened my eyes to new possibilities. At first, I was just going to make the LED light system. However, Rudi said that it was too dull and needed more interactivity. So I looked back at recitation 7 and found out that I could make a lighting mode for when the user is studying that is not too distracting. Rudi suggested that I use an infrared sensor to control the LEDs. I also thought this was a great idea but thought it might be too much because there are many different hand gestures that I would have to account for. I also had trouble setting up the infrared sensors. I was going to make them into a housing unit like a watch that the user would wear, but I thought that would be annoying since the user would be connected through wires and might find wearing the sensor troublesome. However, I was having trouble getting the infrared sensors to work, so I ended up switching to ultrasonic and used different distance values to trigger different functions. I think the ultrasonic sensor was the best for my project as it accurately measured the distance the user would place their hand away from the sensor. This is all the data I needed for my circuit to function. I wanted to make a simple circuit that wasn’t too complicated or required the user to do too much. Since studying is already complicated, there’s no need to overcomplicate the helper. A significant failure of the project was everything not working together. I essentially had three working modes for my project. But the problem was merging them together so they could work one with one another. I think this was a problem with Arduino not being unable to run multiple modes simultaneously. This is because even when I merged the code, the circuit wasn’t working well together. But all three aspects of the project were fully functioning. The study music lighting sequence worked and reacted to the music. The alarm sequence also worked well and reacted to the alarm’s amplitude. It differed from the study lighting sequence as it used RGB. Lastly, the ultrasonic sensor worked well as well since it was reading the distance values of my hand when I interacted with it. The problem lay in getting everything to work with one another.
Conclusion:
All in all, my project was meant to create a study, focus-inducive environment by allowing the user to be immersed and interact with the study buddy while simultaneously limiting external distractions. My project achieved my goals for it to some extent. I think my audience interacted with my project well despite not all the working parts being able to cooperate with one another. I think the audience was able to see what I was trying to accomplish and were able to interact with what was working. I define interaction as an exchange of actions between participants, such as listening, thinking, and speaking. During this encounter, they will react to one another and then act based on their reactions. My project aligns with this definition as the user interacts with the ultrasonic sensor to either turn the circuit off or restart it. Furthermore, the music being played causes different lighting sequences to be carried out based on what song is being played. Thus, there is an exchange of actions between the lights and music. If I had more time, I would use another Arduino so the three modes I have could operate together. Or find another way to make my three components work with one another. I would also make the study area bigger for those who prefer the cubicle-style study environment. This will give them more space to do their work, and I can increase the ultrasonic sensor’s distance interval making it easier to turn off or reactivate my circuit. I learned from setbacks that formatting my code is essential as it allows me to read it better and follow the work I was doing more easily. Other setbacks required me to reach out to professors and Fellows for help, which I greatly benefitted from. I learned to reach out more and not be afraid to ask for help. Some things I take away from my accomplishments are the rewarding feeling of getting something to work on after hours and hours of problem-solving. As well as time management skills. It took a lot of time management skills to finish this project as I needed to plan how much work I would do at certain times So I wouldn’t get burnt out. I think people should care as time management can apply to many other things, not just this project. This can be applied to jobs, other school work, and social relationships. Time management is an essential skill to have. I like the basis of my project and its goals. It poses a unique solution for a common problem that many people, including myself, struggle with. Unfortunately, it doesn’t work as well as I had hoped it would but I did learn a lot from this project and had a lot of fun doing it!
Annex:
This is the final wiring of my project.
This was when I tried to use an infrared sensor as the trigger for my other lighting sequences. I then had trouble with it as the values were not picked up in the serial monitor, so I changed it to the ultrasonic sensor. But the plan was to use infrared sensors to read the user’s hand gestures accurately. Unfortunately, I didn’t even get one to work, so two were out of the question.
I laser cut the “study box” I used for my presentation to present my project.
I then laser cut a smaller box to house the ultrasonic sensor and placed that in the cutout on the left of the study box.
Above is a video of the acrylic box I used to house my ultrasonic sensor being laser cut.
Here me struggling with the alarm code
3 components:
Study Music
Alarm Sequence:
Ultrasonic Sensor:
My Code:
Processing
Study Music Code:
import processing.sound.*;
SoundFile sample;
Amplitude analysis;
void setup() {
size(640, 480);
// load and play a sound file in a loop
sample = new SoundFile(this, "e.mp3");
sample.loop();
// create the Amplitude analysis object
analysis = new Amplitude(this);
// analyze the playing sound file
analysis.input(sample);
}
void draw() {
println(analysis.analyze());
background(125, 255, 125);
noStroke();
fill(255, 0, 150);
// analyze the audio for its volume level
float volume = analysis.analyze();
// volume is a number between 0.0 and 1.0
// map the volume value to a useful scale
float diameter = map(volume, 0, 1, 0, width);
// draw a circle based on the microphone amplitude (volume)
circle(width/2, height/2, diameter);
}
Final code that incorporated all elements:
import processing.sound.*;
import processing.serial.*;
import osteele.processing.SerialRecord.*;
PFont font;
String time = "010";
int t;
int interval = 10;
int former;
Serial serialPort;
SerialRecord serialRecord;
SoundFile sample1;
SoundFile sample2;
Amplitude analysis;
FFT fft;
int bands = 1024;
float smoothingFactor = 0.1;
float[] sum = new float[bands];
int scale = 10;
float barWidth;
int W; //width of the tiles
int NUM = 60; //amount of pixels
int[] r = new int[NUM]; //red of each tile
int[] g = new int[NUM]; //red of each tile
int[] b = new int[NUM]; //red of each tile
void setup() {
size(1450, 800);
background(0);
barWidth = 10*width/float(bands);
// load and play a sound file in a loop
sample1 = new SoundFile(this, "e.mp3");
sample2 = new SoundFile(this, "final.mp3");
sample1.loop();
fft = new FFT(this, bands);
fft.input(sample1);
// create the Amplitude analysis object
analysis = new Amplitude(this);
// analyze the playing sound file
analysis.input(sample1);
W = width/NUM;
// You can use this syntax and change COM3 for your serial port
// printArray(Serial.list());
// serialPort = new Serial(this, "COM3", 9600);
// in MacOS it looks like "/dev/cu.usbmodem1101"
//or you can try to use this instead:
String serialPortName = SerialUtils.findArduinoPort();
serialPort = new Serial(this, serialPortName, 9600);
serialRecord = new SerialRecord(this, serialPort, 6);
serialRecord.logToCanvas(false);
rectMode(CENTER);
}
void draw() {
//background(0);
// if (mousePressed == true) {
// int n = floor(constrain(mouseX/W , 0, NUM-1));
// r[n] = floor(random(255));
// g[n] = floor(random(255));
// b[n] = floor(random(255));
// serialRecord.values[0] = n; // which pixel we change (0-59)
// serialRecord.values[1] = r[n]; // how much red (0-255)
// serialRecord.values[2] = g[n]; // how much green (0-255)
// serialRecord.values[3] = b[n]; // how much blue (0-255)
// serialRecord.send(); // send it!
// }
// println(analysis.analyze());
// background(125, 255, 125);
// noStroke();
// fill(255, 0, 150);
// // analyze the audio for its volume level
// float volume = analysis.analyze();
// // volume is a number between 0.0 and 1.0
// // map the volume value to a useful scale
// int diameter = floor(map(volume, 0, 0.6, 0, 60));
// for(int n = 0; n < diameter; n++) {
// r[n] = floor(random(255));
// g[n] = floor(random(255));
// b[n] = floor(random(255));
// serialRecord.values[0] = n; // which pixel we change (0-59)
// serialRecord.values[1] = r[n]; // how much red (0-255)
// serialRecord.values[2] = g[n]; // how much green (0-255)
// serialRecord.values[3] = b[n]; // how much blue (0-255)
// serialRecord.send();
// }
// if(former > diameter) {
// for(int m = diameter; m < former; m ++) {
// r[m] = 0;
// g[m] = 0;
// b[m] = 0;
// serialRecord.values[0] = m; // which pixel we change (0-59)
// serialRecord.values[1] = r[m]; // how much red (0-255)
// serialRecord.values[2] = g[m]; // how much green (0-255)
// serialRecord.values[3] = b[m]; // how much blue (0-255)
// serialRecord.send();
// }
// }
// former = diameter;
println(analysis.analyze());
background(0);
long t = millis();
fft.analyze();
float volume = analysis.analyze();
// volume is a number between 0.0 and 1.0
// map the volume value to a useful scale
float diameter1 = floor(map(volume, 0, 1, 0, width));
if (t < 18000) {
for (int i = 0; i < bands; i++) {
// Smooth the FFT spectrum data by smoothing factor
sum[i] += (fft.spectrum[i] - sum[i]) * smoothingFactor;
// Draw the rectangles, adjust their height using the scale factor
fill(0, 0, (diameter1)/3);
rect(i*barWidth, height, barWidth, -sum[i]*height*scale);
}
int blue = floor(map(volume, 0, 1, 0, 255));
serialRecord.values[0] = 0;
serialRecord.values[1] = 0;
serialRecord.values[2] = blue;
serialRecord.values[3] = 0;
serialRecord.values[4] = 0;
serialRecord.send();
} else if ((t >= 18000) && t < 28000) {
for (int i = 0; i < bands; i++) {
// Smooth the FFT spectrum data by smoothing factor
sum[i] += (fft.spectrum[i] - sum[i]) * smoothingFactor;
// Draw the rectangles, adjust their height using the scale factor
fill((diameter1)/3, 0, (diameter1)/3);
rect(i*barWidth, height, barWidth, -sum[i]*height*scale);
}
int purple = floor(map(volume, 0, 1, 0, 255));
serialRecord.values[0] = 0;
serialRecord.values[1] = 0;
serialRecord.values[2] = 0;
serialRecord.values[3] = purple;
serialRecord.values[4] = 0;
serialRecord.send();
} else if ((t >= 28000) && t < 38000) {
for (int i = 0; i < bands; i++) {
// Smooth the FFT spectrum data by smoothing factor
sum[i] += (fft.spectrum[i] - sum[i]) * smoothingFactor;
// Draw the rectangles, adjust their height using the scale factor
fill(0, (diameter1)/3, 0);
rect(i*barWidth, height, barWidth, -sum[i]*height*scale);
}
int green = floor(map(volume, 0, 1, 0, 255));
serialRecord.values[0] = 0;
serialRecord.values[1] = green;
serialRecord.values[2] = 0;
serialRecord.values[3] = 0;
serialRecord.values[4] = 0;
serialRecord.send();
} else if ((t >= 38000) && t < 48000) {
for (int i = 0; i < bands; i++) {
// Smooth the FFT spectrum data by smoothing factor
sum[i] += (fft.spectrum[i] - sum[i]) * smoothingFactor;
// Draw the rectangles, adjust their height using the scale factor
fill((diameter1)/3, 0, 0);
rect(i*barWidth, height, barWidth, -sum[i]*height*scale);
}
int red = floor(map(volume, 0, 1, 0, 255));
serialRecord.values[0] = red;
serialRecord.values[1] = 0;
serialRecord.values[2] = 0;
serialRecord.values[3] = 0;
serialRecord.values[4] = 0;
serialRecord.send();
} else if ((t >= 48000) && t < 58000) {
for (int i = 0; i < bands; i++) {
// Smooth the FFT spectrum data by smoothing factor
sum[i] += (fft.spectrum[i] - sum[i]) * smoothingFactor;
// Draw the rectangles, adjust their height using the scale factor
fill(0, (diameter1)/3, (diameter1)/3);
rect(i*barWidth, height, barWidth, -sum[i]*height*scale);
}
int skyblue = floor(map(volume, 0, 1, 0, 255));
serialRecord.values[0] = 0;
serialRecord.values[1] = 0;
serialRecord.values[2] = 0;
serialRecord.values[3] = 0;
serialRecord.values[4] = skyblue;
serialRecord.send();
} else if ((t >= 58000) && t < 68000) {
for (int i = 0; i < bands; i++) {
// Smooth the FFT spectrum data by smoothing factor
sum[i] += (fft.spectrum[i] - sum[i]) * smoothingFactor;
// Draw the rectangles, adjust their height using the scale factor
fill(0, 0, (diameter1)/3);
rect(i*barWidth, height, barWidth, -sum[i]*height*scale);
}
int blue = floor(map(volume, 0, 1, 0, 255));
serialRecord.values[0] = 0;
serialRecord.values[1] = 0;
serialRecord.values[2] = blue;
serialRecord.values[3] = 0;
serialRecord.values[4] = 0;
serialRecord.send();
} else {
sample1.stop();
background(0);
// load and play a sound file in a loop
sample2 = new SoundFile(this, "final.mp3");
sample2.loop();
// create the Amplitude analysis object
analysis = new Amplitude(this);
// analyze the playing sound file
analysis.input(sample2);
//if (mousePressed == true) {
// int n = floor(constrain(mouseX/W , 0, NUM-1));
// r[n] = floor(random(255));
// g[n] = floor(random(255));
// b[n] = floor(random(255));
// serialRecord.values[0] = n; // which pixel we change (0-59)
// serialRecord.values[1] = r[n]; // how much red (0-255)
// serialRecord.values[2] = g[n]; // how much green (0-255)
// serialRecord.values[3] = b[n]; // how much blue (0-255)
// serialRecord.send(); // send it!
// }
println(analysis.analyze());
// analyze the audio for its volume level
serialRecord.read();
int distance = serialRecord.values[5];
if ( distance < 5 ) {
sample2.stop();
sample1.stop();
//for(int n = 0; n < diameter; n++) {
//r[n] = floor(random(255));
//g[n] = floor(random(255));
//b[n] = floor(random(255));
serialRecord.values[0] = 0;
serialRecord.values[1] = 0;
serialRecord.values[2] = 0;
serialRecord.values[3] = 0;
serialRecord.send();
//serialRecord.values[0] = n; // which pixel we change (0-59)
//serialRecord.values[1] = r[n]; // how much red (0-255)
//serialRecord.values[2] = g[n]; // how much green (0-255)
//serialRecord.values[3] = b[n]; // how much blue (0-255)
//serialRecord.send();
}
if((distance >= 10) && distance < 25) {
sample1.loop();
sample2.stop();
for (int i = 0; i < bands; i++) {
// Smooth the FFT spectrum data by smoothing factor
sum[i] += (fft.spectrum[i] - sum[i]) * smoothingFactor;
// Draw the rectangles, adjust their height using the scale factor
fill(0, 0, (diameter1)/3);
rect(i*barWidth, height, barWidth, -sum[i]*height*scale);
}
int blue = floor(map(volume, 0, 1, 0, 255));
serialRecord.values[0] = 0;
serialRecord.values[1] = 0;
serialRecord.values[2] = blue;
serialRecord.values[3] = 0;
serialRecord.send();
// for(int m = diameter; m < former; m ++) {
// r[m] = 0;
// g[m] = 0;
// b[m] = 0;
// serialRecord.values[0] = m; // which pixel we change (0-59)
// serialRecord.values[1] = r[m]; // how much red (0-255)
// serialRecord.values[2] = g[m]; // how much green (0-255)
// serialRecord.values[3] = b[m]; // how much blue (0-255)
// serialRecord.send();
// }
//}
// former = diameter;
}
//r[diameter] = floor(random(255));
//g[diameter] = floor(random(255));
//b[diameter] = floor(random(255));
//serialRecord.values[0] = diameter; // which pixel we change (0-59)
//serialRecord.values[1] = r[diameter]; // how much red (0-255)
//serialRecord.values[2] = g[diameter]; // how much green (0-255)
//serialRecord.values[3] = b[diameter]; // how much blue (0-255)
//serialRecord.send();
//draw a circle based on the microphone amplitude (volume)
//circle(width/2, height/2, diameter);
}
}
Arduino
Alarm system code:
#include "SerialRecord.h"
#include <FastLED.h>
#define NUM_LEDS 60 // How many leds in your strip?
#define DATA_PIN 3 // Which pin are you connecting Arduino to Data In?
CRGB leds[NUM_LEDS];
// Change this number to the number of values you want to receive
SerialRecord reader(4);
void setup() {
Serial.begin(9600);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS); // Initialize
FastLED.setBrightness(10); // BEWARE: external power for full (255)
//further info at https://learn.adafruit.com/adafruit-neopixel-uberguide/powering-neopixels
}
void loop() {
if (reader.read()) {
int n = reader[0];
int r = reader[1];
int g = reader[2];
int b = reader[3];
leds[reader[0]] = CRGB(reader[1], reader[2], reader[3]); // Prepare the color information using CRGB( Red, Green, Blue
FastLED.show(); // Pass the information of color to the LED
}
}
Final Arduino code
#include "SerialRecord.h"
#include <FastLED.h>
#include <NewPing.h>
// #define echoPin 11 // attach pin D2 Arduino to pin Echo of HC-SR04
// #define trigPin 12 //attach pin D3 Arduino to pin Trig of HC-SR04
#define PING_PIN1 11
#define MAX_DISTANCE 400
#define NUM_LEDS 60 // How many leds in your strip?
#define DATA_PIN 3 // Which pin are you connecting Arduino to Data In?
CRGB leds[NUM_LEDS];
// Change this number to the number of values you want to receive
SerialRecord reader(5);
SerialRecord writer(1);
NewPing sonar1(PING_PIN1, PING_PIN1, MAX_DISTANCE);
long duration; // variable for the duration of sound wave travel
int distance; // variable for the distance measurement
void setup() {
Serial.begin(9600);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS); // Initialize
FastLED.setBrightness(30); // BEWARE: external power for full (255)
//further info at https://learn.adafruit.com/adafruit-neopixel-uberguide/powering-neopixels
// pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
// pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
Serial.begin(9600); // // Serial Communication is starting with 9600 of baudrate speed
Serial.println("Ultrasonic Sensor HC-SR04 Test"); // print some text in Serial Monitor
Serial.println("with Arduino UNO R3");
}
void loop() {
if (reader.read()) {
int r = reader[0];
int g = reader[1];
int b = reader[2];
int p = reader[3];
int s = reader[4];
if (r != 0) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(r, 0, 0);
}
FastLED.show();
} if (g != 0) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(0, g, 0);
}
FastLED.show();
} if (b != 0) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(0, 0, b);
}
FastLED.show();
} if (p != 0) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(p, 0, p);
}
FastLED.show();
} if (s != 0) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(0, s, s);
}
FastLED.show();
leds[reader[0]] = CRGB(reader[1], reader[2], reader[3]); // Prepare the color information using CRGB( Red, Green, Blue
FastLED.show();
}
}
// Clears the trigPin condition
// digitalWrite(trigPin, LOW);
// delayMicroseconds(2);
// // Sets the trigPin HIGH (ACTIVE) for 2 microseconds
// digitalWrite(trigPin, HIGH);
// delayMicroseconds(2);
// digitalWrite(trigPin, LOW);
// // Reads the echoPin, returns the sound wave travel time in microseconds
// duration = pulseIn(echoPin, HIGH);
// // Calculating the distance
// distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
// // Displays the distance on the Serial Monitor
// Serial.print("Distance: ");
// Serial.print(distance);
// Serial.println("cm");
delay(50);
int distance = sonar1.ping_cm();
Serial.print("Ping1: ");
Serial.print(distance);
Serial.println("cm");
writer[5] = distance;
writer.send();
delay(50);
}