All Posts

Final Project update – Daniel and Q M Naushad

CONEPT

Our final project will be a mixer using an arduino board and P5js’ sound library.

DESIGN

The mixer will use the following components:

    • 1 potentiometer – analog input (Will work like a slider would in an actual mixer)
    • 2 buttons to switch between effects
    • 1 button to work as a Pause/Play button
    • [MAYBE] 1 button to work as a Bypass/Standby function

Here is a sketch of what it would look like:

We will use the Arduino’s box  to make the board and double as a place to hide the board.

The interface where you will mix is looking like this, currently I am working on it and designing it, this is not the final product/result as we’d like to add some color to it:

The line at the middle will react to the sound and hopefully produce colors and make a sound wave.

FUTURE PLANS

During the week we expect to finish the interface and Arduino set-up, and would be working on the code and synching in the sounds.

Only project that may come is being able to translate the values from the potentiometer to the parameters to make the effects take effect.

Final Project update – Daniel and Q M

conept

Our final project will be a mixer using an arduino board and P5js’ sound library.

Design

The mixer will use the following components:

    • 1 potentiometer – analog input (Will work like a slider would in an actual mixer)
    • 2 buttons to switch between effects
    • 1 button to work as a Pause/Play button
    • [MAYBE] 1 button to work as a Bypass/Standby function

Here is a sketch of what it would look like:

We will use the Arduino’s box  to make the board and double as a place to hide the board.

The interface where you will mix is looking like this, currently I am working on it and designing it, this is not the final product/result as I’d like to add some color to it:

The line at the middle will react to the sound and hopefully produce colors and make a sound wave.

Future plans

During the week we expect to finish the interface and Arduino set-up, and would be working on the code and synching in the sounds.

Only project that may come is being able to translate the values from the potentiometer to the parameters to make the effects take effect.

final project commitment & progress

CONCEPT

In our last post we had come up with a game for our final project. After some further brainstorming, we thought it would be fun to try something other than a game, considering that this is what we did for our midterms. We thought about making an interactive system that could be experienced by multiple people at the same time. Our idea for the project is now to create a touchable “friendship lamp.” The basic idea is that we will build two lamps using two Arduino boards and LED strips. Each light will be equipped with different settings that can change the light pattern and color. These settings will be able to be manipulated within a program on p5.js, accessed on separate computers by the two users. After one user chooses the settings of their light, they then touch their lamp to send that light to the other user’s lamp. Communication between the two users can be simultaneous and there is no limit to the amount of times they can send each other messages. 

THE ROLE OF P5.js 

The sketch on p5.js will be a simple program with a few screens that allows the user to control the light they will send. They will be able to choose any color from a color wheel, and they will be able to choose from 3 different light modes: flicker, wave, and pulse. The choices made by the user will be stored by the program, and p5 will then send this data to the board of the other person’s lamp. However, data is not sent until some feedback is received from Arduino, explained in detail in the following section. 

 

THE ROLE OF ARDUINO 

A touch sensor and an LED strip would both be included in the Arduino circuit. When touched, the touch sensor transmits a signal to p5js, enabling p5js to transfer data to the Arduino board. Since p5js will be sending data about the color and pattern that the LED strip should light up in, the arduino board receives this data and turns the light on as requested by the user.

 

COMMUNICATION

As for the method of communication (serial mode) between the Arduino and p5js, we are still employing wires to transfer data back and forth at the time. However, because the two lamps and users in our original concept must be distanced from one another, we are exploring and, ideally, planning to include Bluetooth modules or, perhaps, an esp32 on our board to help with wireless communication between the two platforms.

PROGRESS 

We knew that we weren’t going to be able to have cross communication between two users without wireless Arduino boards, and that we would not be able to implement the touching aspect without an actual tactile sensor. Hence, our plan for this week was to finalize our idea and begin assembling the different components of the system separately. The p5 program is almost complete, with an exception to the code that will send the data to the wireless Arduino board. The sketch is shown below:

At the end of the program, the console prints out the data that would theoretically be sent to Arduino. Including the color value and the light mode. Also, because we do not have the tactile sensor yet, the light is “sent” figuratively by just pressing any key in the third step. 

For the Arduino component, we built our strips of 10 LED’s for each lamp and connected them to a board and focused on simply creating three different light modes that could be controlled within the Arduino code, separate from p5. The code that demonstrates how the various light modes are used to enable a flicker, wavy, or fading effect on the LED strip is provided below:

void loop() {
  NeoPixel.clear(); // set all pixel colors to 'off'. It only takes effect if pixels.show() is called
  NeoPixel.show();
  // WAVY
  //turn pixels to green one by one with delay between each pixel
  for (int pixel = 0; pixel < NUM_PIXELS; pixel++) { // for each pixel
    NeoPixel.setPixelColor(pixel, NeoPixel.Color(0, 255, 0)); // it only takes effect if pixels.show() is called
    // if(pixel > 0)
    // {
    //   NeoPixel.show();   // send the updated pixel colors to the NeoPixel hardware.
    //   NeoPixel.clear();
    // }
    NeoPixel.show();   // send the updated pixel colors to the NeoPixel hardware.
    NeoPixel.clear();
    
    delay(100); // pause between each pixel
  }
  // turn off all pixels for two seconds
  NeoPixel.clear();
  NeoPixel.show(); // send the updated pixel colors to the NeoPixel hardware.
  delay(2000);     // off time
  // FLICKERING:
  //turn on all pixels to red at the same time for two seconds
  for (int pixel = 0; pixel < NUM_PIXELS; pixel++) { // for each pixel
    NeoPixel.setPixelColor(pixel, NeoPixel.Color(255, 0, 0)); // it only takes effect if pixels.show() is called
  }
  NeoPixel.show(); // send the updated pixel colors to the NeoPixel hardware.
  delay(500);     // on time
  // turn off all pixels for two seconds
  NeoPixel.clear();
  NeoPixel.show(); // send the updated pixel colors to the NeoPixel hardware.
  delay(500);     // off time
  //PULSING
  brighten();
  darken();
}
// 0 to 255
void brighten() {
  uint16_t i, j;
  for (j = 0; j < 255; j++) {
    for (i = 0; i < NeoPixel.numPixels(); i++) {
      NeoPixel.setPixelColor(i, 0, 0, j);
    }
    NeoPixel.show();
    delay(10);
  }
  //delay(100);
}
// 255 to 0
void darken() {
  Serial.begin(9600);
  uint16_t i, j;
  for (j = 255; j > 0; j--) {
    for (i = 0; i < NeoPixel.numPixels(); i++) {
      NeoPixel.setPixelColor(i, 0, 0, j);
    }
    NeoPixel.show();
    delay(10);
    Serial.println(j);
  }
  delay(100);
}

 

Finally, a demo of the different modes is displayed below:

 

Final Project – Progress

Concept/ Idea

For the project, we (Tim and Samyam) have decided to develop a system that lets the user sketch a diagram or shape on the p5.js canvas. This sketch then will be used to control the physical arm of our drawing platform. To accomplish this, we will send canvas data from p5.js to Arduino, controlling different parts of the drawing device. 

The striking feature of the project is the interconnectivity of the drawing. The user can draw as many shapes or sketches as they desire, but everything will remain connected to each other. This idea is inspired by the Eulerian trail, where the floor is divided into multiple sections when multiple people step on it. 

 

Hardware Design

Following the previous post, we have finalized our concept to be a polar coordinate pen plotter that plots a shape drawn on the computer screen. Unlike our previous design, we have decided to make a 2-DOF system (linear movement on one axis, and rotational motion around an orthogonal axis). Although the mechanical design of the machine became more complex, this will make the software much simpler. For the design, we used Autodesk Fusion 360 to create a 3d model, which was manufactured with a 3d printer and a laser cutter. For the precision of the plotter, we purchased a linear guide rail, commonly used in CNC machines and 3d printers; we used a stepper motor for controlled movement. Below is a 3 d model design for the project:

A rack and pinion system was used, so as a gear connected to a stepper motor rotates, it will move the whole pen carrier along a linear rail.

One distinctive feature of this plotter is that the position of the rotating (base) plate can be adjusted freely. This allows the user to produce different drawings every time he or she moves the base plate.

Because drawings on the screen use cartesian coordinates, we had to convert XY coordinates into polar coordinates. This was very simple because T:(X,Y) –> (r, θ), where r = sqrt(x^2+y^2) and θ = tan^-1(y/x). r will determine the movement of a linear DOF and θ will determine how much the base plate will rotate. Do you see how simple the calculation got compared to the previous design?

Making Parts

As mentioned above, a laser cutter and 3d printer was used to make parts.

Prototype

Laser Cutting

Due to the high rigidity of the acrylic plates, we decided to make the main body with acrylic parts. Based on our design, we were able to laser-cut the parts that we needed.

3D Printing

Parts that cannot be made with laser cutters were made using 3d printers. This included a base plate, a spacer between acrylic parts, and a pen moving mechanism.

P5.js Component

The preliminary phase of the project depends on the functionalities of the p5.js component. The user can use the mouse to draw shapes on the p5.js canvas; the shape will be replicated in the actual design using the Arduino component. 

In order to sketch a shape on the canvas, the user can click the mouse and drag the cursor to draw the desired shape. This is regulated by two functions titled “mousePressed()” and “mouseReleased()” respectively. When the mouse is clicked, the global variable “isclicked” is set to True and when the mouse click is released, “isClicked” is set to False. This way, the global variable keeps track of the sketch being drawn. 

Once the mouse is clicked, the program checks the position of the cursor – if it is static while being tracked, the position is ignored, i.e., the user must move the cursor, while the mouse is being clicked, so that a sketch can be drawn on the screen. It is facilitated by the following code:

// Make sure the mouse is clicked and cursor position is different
if (isClicked && mouseX !== pmouseX && mouseX !== pmouseY)
{
  // Create a vector and add it to the list
  // let pt = createVector(mouseX, mouseY);          // When origin is at the top-left corner
  let pt = createVector(mouseX - width/2, mouseY - height/2);
  positions.push(pt);
  // console.log(pt.x, pt.y);
  
  
  // Mapping Cartesian to Polar and appending it in mappedPositions array
  let temp_list = [];
  temp_list = cartToPolar(pt.x, pt.y)
  let pt_mapped = createVector((temp_list[0] * one_px_mm), temp_list[1]);
  mappedPositions.push(pt_mapped);
 
}

Here, we can see, if the aforementioned conditions are met, a new vector based on the cartesian location of the cursor is created and appended to the (global variable) list “positions”. The entire canvas is translated to the middle of the canvas, that’s why a certain amount is subtracted to the x and y coordinates before appending to the list. Similarly, with the help of a function titled “cartToPolar()”, each vector in the cartesian coordinates is converted to polar coordinates equivalent and appended to a list titled “mappedPositions[]”.

function cartToPolar(x, y)
{
  let radius, angle;
  
  radius = sqrt(sq(x) + sq(y));
  // console.log(radius);
  
  angle = atan(y/x);
  // console.log(angle);
  
  let temp_list = [];
  temp_list[0] = map(radius, 0, sqrt(2 * sq(width/2)), 0, disc_radius);         // Mapped radius
  temp_list[1] = angle;
  
  return temp_list;
  
}

The program also consists of two manually coded buttons — RESET and SEND DATA. The former reset the canvas and resets the required variables so that the sketch can be redrawn from the beginning. While the latter is used to send data to the Arduino connected to the system. Both these functions derive from a template function titled “button()” that takes text, x, y coordinates, height and width of the button as arguments. To develop the SEND DATA functionality, a function named “send_data_button()” calls the main button function with the required parameters. The main function returns a boolean value [1 if the cursor is within the button and 0 otherwise]. If the boolean value is 1 and the button is pressed, the values in the “mappedPositions[]” list are forwarded to the Arduino using an inbuilt serial.write() function. In each iteration, the angle of the coordinate is transmitted following its radius. 

function reset_button()
{
  let x = 26;
  let y = canvas_h - 70;
  let w = 125;
  let h = 50;
  
  // If the cursor is within the button button() function returns 1, else 0;
  let resetBool = button("RESET", x, y, w, h);
  
  // Resetting sketch if the cursor iswithin the button and mouse is clicked
  if (resetBool && mouseIsPressed)
  {
    positions = [];
    mappedPositions = [];
    isClicked = false;
  }
  
}

 

The p5.js component also comprises different functions like choosePort(), openPort(), serialEvent() and so forth to keep track of the port selection, data transmission as well as error handling. 

Arduino Component

Arduino is connected to 2 stepper motors, each controlled by different stepper drivers. The Arduino will read data sent from p5js and move the pen and plate accordingly. Total of 2 switches will be connected to the board, both for homing the pen carrier (one push button and one limit switch).

When the button is pressed, the Arduino will begin to move the pen carrier back until the carrier hits the limit switch. Once the limit switch is closed, the Arduino will move the pen carrier slightly front and move the carrier back until it hits the switch again. The second part will be done at a much slower speed for accuracy. Homing a pen carrier is significant because the machine must always be aware of the pen’s current position. Homing allows the machine to always start from the same initial position.

This is the sample code showing how the code will work (no motors added yet):

const int limitSw = 7;

const int homeButt = 8;

long long currentTime = 0;

bool homing = false;

bool reachEnd = false;

void setup() {

  // put your setup code here, to run once:

  pinMode(limitSw, INPUT);

  pinMode(homeButt, INPUT);

  Serial.begin(9600); 

}


void loop() {

  // put your main code here, to run repeatedly:

  if(!homing && digitalRead(homeButt) == 1){

    homing = true;

  }


  if(homing){

    if(!reachEnd){

      Serial.println("homing fast");

      if(digitalRead(limitSw) == 1){

        Serial.println("SW pressed");

        reachEnd = true;

        currentTime = millis();

      }

    }

    else{

      Serial.println("homing slow");

      if(digitalRead(limitSw) == 1 && millis() - currentTime > 500){

        Serial.println("SW slow pressed. homing complete");

        homing = false;

        reachEnd = false;

      }

    }

  }

}

The other part of the code will include moving each part accordingly to the coordinate values from p5js. This would be relatively easy to achieve because we can calculate how much each part will move in mm when the motor turns by half or a single step.

Further coding can be done once we are ready with fully assembled hardware.

Future Plan

The time it takes to 3D print parts is the only problem we are facing until now. Once we are done printing our parts, we will be able to assemble the parts together soon. 

For now, the future plan includes the functionality to successfully coordinate the Arduino component with the data sent from the p5.js component. Since the canvas sketch is drawn based on cartesian coordinates, while the physical drawing is based on polar coordinates, we are planning to program the project so that artistic output is achieved. 

Demo

The software phase of the project can be tested here using this link. The project will be completed once the printing phase is completed.

Final Project Update 1

Concept/ Idea

For the project, we (Tim and Samyam) have decided to develop a system that lets the user sketch a diagram or shape on the p5.js canvas. This sketch then will be used to control the physical arm of our drawing platform. To accomplish this, we will send canvas data from p5.js to Arduino, controlling different parts of the drawing device.

The striking feature of the project is the interconnectivity of the drawing. The user can draw as many shapes or sketches as they desire, but everything will remain connected to each other. This idea is inspired by the Eulerian trail, where the floor is divided into multiple sections when multiple people step on it.

 

Hardware Design

Following the previous post, we have finalized our concept to be a polar coordinate pen plotter that plots a shape drawn on the computer screen. Unlike our previous design, we have decided to make a 2-DOF system (linear movement on one axis, and rotational motion around an orthogonal axis). Although the mechanical design of the machine became more complex, this will make the software much simpler. For the design, we used Autodesk Fusion 360 to create a 3d model, which was manufactured with a 3d printer and a laser cutter. For the precision of the plotter, we purchased a linear guide rail, commonly used in CNC machines and 3d printers; we used a stepper motor for controlled movement. Below is a 3 d model design for the project:

A rack and pinion system was used, so as a gear connected to a stepper motor rotates, it will move the whole pen carrier along a linear rail.

One distinctive feature of this plotter is that the position of the rotating (base) plate can be adjusted freely. This allows the user to produce different drawings every time he or she moves the base plate.

Because drawings on the screen use cartesian coordinates, we had to convert XY coordinates into polar coordinates. This was very simple because T:(X,Y) –> (r, θ), where r = sqrt(x^2+y^2) and θ = tan^-1(y/x). r will determine the movement of a linear DOF and θ will determine how much the base plate will rotate. Do you see how simple the calculation got compared to the previous design?

Making Parts

As mentioned above, a laser cutter and 3d printer was used to make parts.

Prototype

Laser Cutting

Due to the high rigidity of the acrylic plates, we decided to make the main body with acrylic parts. Based on our design, we were able to laser-cut the parts that we needed.

3D Printing

Parts that cannot be made with laser cutters were made using 3d printers. This included a base plate, a spacer between acrylic parts, and a pen moving mechanism.

P5.js Component

The preliminary phase of the project depends on the functionalities of the p5.js component. The user can use the mouse to draw shapes on the p5.js canvas; the shape will be replicated in the actual design using the Arduino component.

In order to sketch a shape on the canvas, the user can click the mouse and drag the cursor to draw the desired shape. This is regulated by two functions titled “mousePressed()” and “mouseReleased()” respectively. When the mouse is clicked, the global variable “isclicked” is set to True and when the mouse click is released, “isClicked” is set to False. This way, the global variable keeps track of the sketch being drawn.

Once the mouse is clicked, the program checks the position of the cursor – if it is static while being tracked, the position is ignored, i.e., the user must move the cursor, while the mouse is being clicked, so that a sketch can be drawn on the screen. It is facilitated by the following code:

// Make sure the mouse is clicked and cursor position is different
if (isClicked && mouseX !== pmouseX && mouseX !== pmouseY)
{
  // Create a vector and add it to the list
  // let pt = createVector(mouseX, mouseY);          // When origin is at the top-left corner
  let pt = createVector(mouseX - width/2, mouseY - height/2);
  positions.push(pt);
  // console.log(pt.x, pt.y);
  
  
  // Mapping Cartesian to Polar and appending it in mappedPositions array
  let temp_list = [];
  temp_list = cartToPolar(pt.x, pt.y)
  let pt_mapped = createVector((temp_list[0] * one_px_mm), temp_list[1]);
  mappedPositions.push(pt_mapped);
 
}

Here, we can see, if the aforementioned conditions are met, a new vector based on the cartesian location of the cursor is created and appended to the (global variable) list “positions”. The entire canvas is translated to the middle of the canvas, that’s why a certain amount is subtracted to the x and y coordinates before appending to the list. Similarly, with the help of a function titled “cartToPolar()”, each vector in the cartesian coordinates is converted to polar coordinates equivalent and appended to a list titled “mappedPositions[]”.

function cartToPolar(x, y)
{
  let radius, angle;
  
  radius = sqrt(sq(x) + sq(y));
  // console.log(radius);
  
  angle = atan(y/x);
  // console.log(angle);
  
  let temp_list = [];
  temp_list[0] = map(radius, 0, sqrt(2 * sq(width/2)), 0, disc_radius);         // Mapped radius
  temp_list[1] = angle;
  
  return temp_list;
  
}

The program also consists of two manually coded buttons — RESET and SEND DATA. The former reset the canvas and resets the required variables so that the sketch can be redrawn from the beginning. While the latter is used to send data to the Arduino connected to the system. Both these functions derive from a template function titled “button()” that takes text, x, y coordinates, height and width of the button as arguments. To develop the SEND DATA functionality, a function named “send_data_button()” calls the main button function with the required parameters. The main function returns a boolean value [1 if the cursor is within the button and 0 otherwise]. If the boolean value is 1 and the button is pressed, the values in the “mappedPositions[]” list are forwarded to the Arduino using an inbuilt serial.write() function. In each iteration, the angle of the coordinate is transmitted following its radius.

function reset_button()
{
  let x = 26;
  let y = canvas_h - 70;
  let w = 125;
  let h = 50;
  
  // If the cursor is within the button button() function returns 1, else 0;
  let resetBool = button("RESET", x, y, w, h);
  
  // Resetting sketch if the cursor iswithin the button and mouse is clicked
  if (resetBool && mouseIsPressed)
  {
    positions = [];
    mappedPositions = [];
    isClicked = false;
  }
  
}

 

The p5.js component also comprises different functions like choosePort(), openPort(), serialEvent() and so forth to keep track of the port selection, data transmission as well as error handling.

Arduino Component

Arduino is connected to 2 stepper motors, each controlled by different stepper drivers. The Arduino will read data sent from p5js and move the pen and plate accordingly. Total of 2 switches will be connected to the board, both for homing the pen carrier (one push button and one limit switch).

When the button is pressed, the Arduino will begin to move the pen carrier back until the carrier hits the limit switch. Once the limit switch is closed, the Arduino will move the pen carrier slightly front and move the carrier back until it hits the switch again. The second part will be done at a much slower speed for accuracy. Homing a pen carrier is significant because the machine must always be aware of the pen’s current position. Homing allows the machine to always start from the same initial position.

This is the sample code showing how the code will work (no motors added yet):

const int limitSw = 7;

const int homeButt = 8;

long long currentTime = 0;

bool homing = false;

bool reachEnd = false;

void setup() {

  // put your setup code here, to run once:

  pinMode(limitSw, INPUT);

  pinMode(homeButt, INPUT);

  Serial.begin(9600); 

}


void loop() {

  // put your main code here, to run repeatedly:

  if(!homing && digitalRead(homeButt) == 1){

    homing = true;

  }


  if(homing){

    if(!reachEnd){

      Serial.println("homing fast");

      if(digitalRead(limitSw) == 1){

        Serial.println("SW pressed");

        reachEnd = true;

        currentTime = millis();

      }

    }

    else{

      Serial.println("homing slow");

      if(digitalRead(limitSw) == 1 && millis() - currentTime > 500){

        Serial.println("SW slow pressed. homing complete");

        homing = false;

        reachEnd = false;

      }

    }

  }

}

The other part of the code will include moving each part accordingly to the coordinate values from p5js. This would be relatively easy to achieve because we can calculate how much each part will move in mm when the motor turns by half or a single step.

Further coding can be done once we are ready with fully assembled hardware.

Future Plan

The time it takes to 3D print parts is the only problem we are facing until now. Once we are done printing our parts, we will be able to assemble the parts together soon.

For now, the future plan includes the functionality to successfully coordinate the Arduino component with the data sent from the p5.js component. Since the canvas sketch is drawn based on cartesian coordinates, while the physical drawing is based on polar coordinates, we are planning to program the project so that artistic output is achieved.

Demo

The software phase of the project can be tested here using this link. The project will be completed once the printing phase is completed.

Week 12 – Final Project Proposal (Phoebe & Fuad)

CONCEPT

In our last post we had come up with a game for our final project. After some further brainstorming, we thought it would be fun to try something other than a game, considering that this is what we did for our midterms. We thought about making an interactive system that could be experienced by multiple people at the same time. Our idea for the project is now to create a touchable “friendship lamp.” The basic idea is that we will build two lamps using two Arduino boards and LED strips. Each light will be equipped with different settings that can change the light pattern and color. These settings will be able to be manipulated within a program on p5.js, accessed on separate computers by the two users. After one user chooses the settings of their light, they then touch their lamp to send that light to the other user’s lamp. Communication between the two users can be simultaneous and there is no limit to the amount of times they can send each other messages. 

THE ROLE OF P5.js 

The sketch on p5.js will be a simple program with a few screens that allows the user to control the light they will send. They will be able to choose any color from a color wheel, and they will be able to choose from 3 different light modes: flicker, wave, and pulse. The choices made by the user will be stored by the program, and p5 will then send this data to the board of the other person’s lamp. However, data is not sent until some feedback is received from Arduino, explained in detail in the following section. 

THE ROLE OF ARDUINO 

A touch sensor and an LED strip would both be included in the Arduino circuit. When touched, the touch sensor transmits a signal to p5js, enabling p5js to transfer data to the Arduino board. Since p5js will be sending data about the color and pattern that the LED strip should light up in, the Arduino board receives this data and turns the light on as requested by the user.

HOW THEY COMMUNICATE 

As for the method of communication (serial mode) between the Arduino and p5js, we are still employing wires to transfer data back and forth at the time. However, because the two lamps and users in our original concept must be distanced from one another, we are exploring and, ideally, planning to include Bluetooth modules or, perhaps, an esp32 on our board to help with wireless communication between the two platforms.

PROGRESS 

We knew that we weren’t going to be able to have cross communication between two users without wireless Arduino boards, and that we would not be able to implement the touching aspect without an actual tactile sensor. Hence, our plan for this week was to finalize our idea and begin assembling the different components of the system separately. The p5 program is almost complete, with an exception to the code that will send the data to the wireless Arduino board. The sketch is shown below:

At the end of the program, the console prints out the data that would theoretically be sent to Arduino. Including the color value and the light mode. Also, because we do not have the tactile sensor yet, the light is “sent” figuratively by just pressing any key in the third step. 

For the Arduino component, we built our strips of 10 LED’s for each lamp and connected them to a board and focused on simply creating three different light modes that could be controlled within the Arduino code, separate from p5. The code that demonstrates how the various light modes are used to enable a flicker, wavy, or fading effect on the LED strip is provided below:

void loop() {
  NeoPixel.clear(); // set all pixel colors to 'off'. It only takes effect if pixels.show() is called
  NeoPixel.show();


  // WAVY
  //turn pixels to green one by one with delay between each pixel
  for (int pixel = 0; pixel < NUM_PIXELS; pixel++) { // for each pixel
    NeoPixel.setPixelColor(pixel, NeoPixel.Color(0, 255, 0)); // it only takes effect if pixels.show() is called
    // if(pixel > 0)
    // {
    //   NeoPixel.show();   // send the updated pixel colors to the NeoPixel hardware.
    //   NeoPixel.clear();
    // }
    NeoPixel.show();   // send the updated pixel colors to the NeoPixel hardware.
    NeoPixel.clear();
    
    delay(100); // pause between each pixel
  }

  // turn off all pixels for two seconds
  NeoPixel.clear();
  NeoPixel.show(); // send the updated pixel colors to the NeoPixel hardware.
  delay(2000);     // off time


  // FLICKERING:
  //turn on all pixels to red at the same time for two seconds
  for (int pixel = 0; pixel < NUM_PIXELS; pixel++) { // for each pixel
    NeoPixel.setPixelColor(pixel, NeoPixel.Color(255, 0, 0)); // it only takes effect if pixels.show() is called
  }
  NeoPixel.show(); // send the updated pixel colors to the NeoPixel hardware.
  delay(500);     // on time

  // turn off all pixels for two seconds
  NeoPixel.clear();
  NeoPixel.show(); // send the updated pixel colors to the NeoPixel hardware.
  delay(500);     // off time

  //PULSING
  brighten();
  darken();
}


// 0 to 255
void brighten() {
  uint16_t i, j;

  for (j = 0; j < 255; j++) {
    for (i = 0; i < NeoPixel.numPixels(); i++) {
      NeoPixel.setPixelColor(i, 0, 0, j);
    }
    NeoPixel.show();
    delay(10);
  }
  //delay(100);
}

// 255 to 0
void darken() {
  Serial.begin(9600);
  uint16_t i, j;

  for (j = 255; j > 0; j--) {
    for (i = 0; i < NeoPixel.numPixels(); i++) {
      NeoPixel.setPixelColor(i, 0, 0, j);
    }
    NeoPixel.show();
    delay(10);
    Serial.println(j);
  }
  delay(100);
}

Finally, a demo of the different modes is displayed below:

Finalized Project Concept

Finalized concept

For my final project (I’m doing it solo), I decided to make a radio that changes FM values according to what number you turn the potentiometer dial to (I will input song files that play according to their designated serial monitor value).

Each range of values will take you to a different channel.

This includes:

  • 4-204 (Hip Hop)
  • 205-408 (Historic Events)
  • 409-612 (Classic Rock/ Oldies)
  • 613-816 (Classical)
  • 817-1023 (Khaleeji)

For 0-3 Radio is switched off.

Assembly

To assemble the circuit, I connected 5 different color LEDs to a digital pin on the anode ends, and to each cathode, I connected a resistor. I then connected a potentiometer dial to an analog pin (along with 5V and GND).

Arduino Code

So far, my Arduino code works separately from p5. I’m having trouble connecting both, as I’m trying to convert the 1023 ASCII serial monitor values to p5 without having to change it to 255.

My code generally consists of if statements designating each range of potentiometer values to each LED.

Example:

if ((potMeasure > 3) && (potMeasure <= 204)) {
  digitalWrite (redPin, HIGH);
  digitalWrite (yellowPin, LOW);
  digitalWrite (greenPin, LOW);
  digitalWrite (tealPin, LOW);
  digitalWrite (bluePin, LOW);
}
else if ((potMeasure > 204) && (potMeasure < 409)) {
  digitalWrite (yellowPin, HIGH);
  digitalWrite (redPin, LOW);
  digitalWrite (greenPin, LOW);
  digitalWrite (tealPin, LOW);
  digitalWrite (bluePin, LOW);
}

The inputs are the LEDs, and the output is the single potentiometer.

p5 Code

I have the p5 code for the serial monitor that picks up values from 0-255, but I’m not sure how to change it so that it can pick up values from 0-1023.

I’m trying to make it so that when inData is between the designated range of values for each channel, it would display the channel name and also play a random song from the designated array of mp3 files.

p5 Screen Design

 

 

 

 

 

 

 

This is the design I made so far, but it of course could be subject to change later on!

Final – Proposal

To imagine that we are already at our final project! It seems like only yesterday that I was figuring out the arc() function in p5.js—yet here we are, preparing for the finale. The task is to harness the powers of both p5.js and Arduino in tandem, and I’m looking forward to see if I can realize a certain vision I’ve had in mind for a while now . . .

The Inspiration & Idea

My inspiration is the ocarina mechanic in Legend of Zelda: Ocarina of Time. In the game, the main character Link possesses a magical ocarina that can have certain effects on the surrounding environment when certain melodies are played; for example, the Sun’s Song can change night to day and vice verse, while Zelda’s Lullaby is used to solve various puzzles (like opening doors with a certain insignia on them).

Since the very beginning of this course, I’ve had the vague vision of implementing this mechanic for my final project—and now that I’ve made it to this point, this vision is looking a little clearer. The plan is to use the musical capabilities of Arduino to build a makeshift instrument (in place of the ocarina), and p5.js to display a sort of environment that can be interacted with through Arduino. For instance, a treasure chest displayed in p5.js could be opened by playing the correct melody (the correct sequence of notes) on Arduino. The biggest feature and question mark here is the method I am going to use to 1) send information to p5.js containing the sequence of notes being played on the Arduino instrument; 2) check if the sequence of the notes being played is a viable melody; and 3) have the according element in the p5.js be impacted.

This will undoubtedly be my most challenging work yet, as I put together everything I have learned throughout this course to bring to life an interactive program that spans both the virtual and the physical. From making a working instrument to creating an interactive virtual environment, there is much to be done here. While I am equal parts excited and nervous about this project, I will only know of its true magnitude when I get into the thick of things. Off to work, then.

Assignment 8: Three Exercises

Exercise 1

This one was a simple matter of adding an ellipse() function (to the Arduino-p5.js connection example) in which the parameter for the x-coordinate is affected by the incoming serial data:

//In the draw function:
ellipse((inData/255 * 400), 200, 30, 30);

This line of code allows the horizontal location of the ellipse to be controlled by the potentiometer.

The link to the full code: https://editor.p5js.org/Ian0730/sketches/Nzxs9rlCa

Exercise 2

For this exercise, I modified Professor Sherwood’s example of bilateral connection so that the value of a variable defined in p5.js named brightness is sent to Arduino and used to control the brightness of an LED. This is the code in p5.js:

//p5.js Code
function draw() {
 ...
  // Click on place on canvas to adjust brightness
  if (mouseIsPressed) {
    brightness = round(map(mouseX, 0, 640, 0, 255));
    print(brightness);
  }
 ...
}
...
//Value of brightness is sent to Arduino
function readSerial(data) {
  if (data != null) {
    //SEND TO ARDUINO HERE
    let sendToArduino = brightness + "\n";
    writeSerial(sendToArduino);
  }
}

As seen in the code, the value of brightness is determined by the x-position of the mouse on the screen. It is then sent to Arduino, which runs the following code:

//Arduino Code
//Initialize Variables
int brightness;
int led1 = 5;
...
void loop() {
  // Wait for data from p5 before doing something
  if (Serial.available()) {
    brightness = Serial.parseInt();  //Arduino brightness = p5 brightness
    Serial.println(brightness);
    delay(30);
    analogWrite(led1, brightness); // Updates brightness of LED
  }
}

A variable also named brightness is constantly updated to match its counterpart in p5.js. It is then used as a parameter for determining the strength of the LED light in the line analogWrite(led1, brightness;. Thus, the LED light gets brighter the closer to the right side of the canvas the mouse cursor is pressed at (and vice versa).

The link to the full code: https://editor.p5js.org/Ian0730/sketches/_jqfjfe8V

Exercise 3

This was the most challenging exercise yet! I first took much of the code from the gravity wind example and implemented it within the aforementioned example of bilateral connection. I then initialized a key variable named bounce for tracking each bounce of the ball, which is then called for this chunk of code in p5.js:

//p5.js Code
function draw() {
  . . .
  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;
      bounce = 1; //Bounce is 1 when ball touches ground
  } else{
    bounce = 0; //Bounce is 0 when ball is midair
  }
  . . .
}
. . .
function readSerial(data) {
  if (data != null) {
    . . .
    //SEND TO ARDUINO HERE
    let sendToArduino = bounce + "\n";
    writeSerial(sendToArduino); //Value of bounce is sent to Arduino
  }
}

According to this code, bounce is 1 when the ball makes/is making contact with the ground, and 0 otherwise; this value is then sent to Arduino and called for the following code:

//Arduino Code
//Initialize Variables
. . .
int led = 5;
int bounce = 0;

void setup() {
  Serial.begin(9600);
  pinMode(5, OUTPUT); //Set pin
  digitalWrite(led, LOW); //Start with LED off
  . . .
  }
}

void loop() {
  // Wait for data from p5 before doing something
  while (Serial.available()) {
    bounce = Serial.parseInt(); //Arduino bounce = p5 bounce
    if (Serial.read() == '\n') {
      digitalWrite(led, bounce); //1 = on, 0 = off
      delay(1);
      . . .
    }
  }
}

Similarly to Exercise 2, a variable also named bounce is constantly updated to match its counterpart in p5.js. It is then used as a parameter for determining whether the LED is on and off in the line digitalWrite(led, bounce;. Thus, the LED light is on when the ball makes contact with the ground and off when it is in midair.

The other portion of the exercise was to use an analog sensor to control the direction of the wind—I decided to use a potentiometer for the task. This is the code used to implement this:

//p5.js Code
function readSerial(data) {
  //READ FROM ARDUINO HERE
  if (data != null) {
    // Collect data from Arduino
    let fromArduino = split(trim(data), ",");
    // If the right length, then proceed
    if (fromArduino.length == 1) {
      // Use value from potentiometer to affect direction of wind
      wind.x = fromArduino[0];
    }
    . . .
  }
}

//Arduino Code
//Initialize Variables
int potentio = A2;
. . .
void loop() {
  while (Serial.available()) {
    . . .
    if (Serial.read() == '\n') { 
      . . .
      //Store potentiometer value
      int potValue = analogRead(potentio);
      delay(1);
      //Split potentiometer into two zones, send value accordingly
      if (potValue < 512){
        Serial.println(-1);
      } else {
        Serial.println(1);
      }
    }
  }
}

As shown in the code above, the possible values of the potentiometer are split into two halves, with each half sending a value of either -1 or  1 to p5.js; values under 512 send -1, and values equal to and above 512  send 1. These values are then used in p5.js to determine the direction of the wind through wind.x = fromArduino[0];; a value of -1 sends the wind blowing to the left, while 1 sends it to the right.

The link to the full code: https://editor.p5js.org/Ian0730/sketches/CMvWY901S

Video

Final Project Vision

Ah, the time has finally come. I can’t believe we are already very close to showcasing everything we’ve learned in this course!

For my final project, I thought I’d like to create a game and also combine the music element in it because I just couldn’t give up either one. And because I am already in my Christmas festive mood, I thought it’d be cute to display a Christmas-related game for the users to play during the showcase!

Because I love playing the dinosaur game, I was thinking of creating a Christmas version of that, as well as including Christmas music/sound effects in the game. I searched it up in case there’s a similar game, and I found one that’s called “Ginger Ninga,” which is pictured below:

(Here’s the link to the game.)

I would like to change some elements of the game while still going with the general idea of having gingerbread man as my main character and having the basic elements that are similar to the dinosaur game. My game will consist of:

  • Five tries (hearts) so that it goes on for longer
  • Christmas-themed background
  • Have presents as the prize icon while having icicles as obstacles
  • Will have the gingerbread man jump over from iceberg to iceberg
  • Each time the gingerbread man collects presents, the game will play a “ho-ho-ho” sound; on the contrary, each time the gingerbread man dies, a sound of “ahh!” will play.
  • Will also play Christmas lofi music in the background:)

I will also have to make sure that the user will be able to play the game by using Arduino instead of the keyboard, which is the part that I’m not too sure about – I’ll probably be using either the switch or the potentiometer to control the gingerbread man’s movement, but this is still up in the air as of now. I’m also thinking of incorporating a red and green LED light so that when the gingerbread man successfully collects “prizes,” the green light will turn on, while if it dies, the red one will turn on.

I’m very excited to get started, but I’m also a little worried about the logistics and the details of it as well. I’ll definitely have to seek out the professor to further discuss about my rough idea!