For this week’s assignment I went with a simple paddle with ball game. the aim is to get the paddle and the bored to touch, their is a count for any times the played either missed or hit the paddle with the ball. The count can be reloaded just by pressing the mouse. The paddle can be moved using the potentiometer. It was very simple to make, however, I did face some difficulty understanding how to connect the Arduino to the processing. eventually after research and watching our class video a couple times , I was able to get it to work.
import processing.serial.*;
float ballX = 200;
float ballY =100;
float speedX= 7;
float speedY= 0;
int hit = 0;
int miss =0;
String serialPortName ="/dev/cu.usbmodem141101";
Serial arduino;
float batPosition;
PImage bat;
void setup () {
size ( 600, 600);
bat = loadImage("bat.png");
if(serialPortName.equals("/dev/cu.usbmodem141101")) scanForArduino();
else arduino = new Serial(this, serialPortName, 9600);
}
void draw() {
if (mousePressed){
hit =0; miss =0;
}
if((arduino != null) && (arduino.available()>0)) {
String message = arduino.readStringUntil('\n');
if(message != null) {
int value = int(message.trim());
batPosition = map(value,0,1024,0,width);
}
}
float paddle =100 ; // can make the paddle get smaller is if i add 1000/ (hit+10)
if (ballX <0 || ballX > width ) speedX = -speedX;
if ( ballY> height) {
speedY = -speedY;
float distance = abs(mouseX - ballX);
if (distance < paddle ) hit += 1;
else miss +=1;
}else speedY +=1;
ballX +=speedX;
ballY +=speedY;
background(0, 0, 0);
ellipse ( ballX, ballY, 50, 50);
image(bat,batPosition,height-bat.height); //rect (width-paddle, height -10, 2*paddle, 10); // where i want to connect the potntiometer cause it is the paddle
text ( " hit :" + hit ,10,30);
text ( " miss :" + miss ,90,30);
}
void stop()
{
arduino.stop();
}
void scanForArduino()
{
try {
for(int i=0; i<Serial.list().length ;i++) {
if(Serial.list()[i].contains("tty.usb")) {
arduino = new Serial(this, Serial.list()[i], 9600);
}
}
} catch(Exception e) {
// println("Cannot connect to Arduino !");
}
}
This is the final demo of the game :
Link for the Game:
this was where I got the code to connect them together: https://www.instructables.com/Getting-started-with-Arduino-Potentiometer-Pong/
For the final project idea :
I have many ideas, but one that can work was actually inspired from an idea that Sarah had a while a go.
Sarah talked one time about a children’s game and i had the idea from that.
The concept would involve, buttons and a potentiometer.
The game would be a learning game for kids, the buttons would represent colors and the potentiometer and be used to draw things like circles and squares.
So far this idea , to me, is a foundational concept I wanna try. What I have pitched is not the whole concept, the further I explore I will be able to see what I can or can’t do and also mainly what I should and shouldn’t do. I believe it’ll be difficult but I do wanna explore this idea and I hope It works out.
During the break room meeting, I pitched this idea to my classmates who were there with me. Nathan gave me such a helpful idea , he said I could try having only two buttons and the my processing could be a type of quiz. I really liked this idea, it could be very simple for kids to learn from and after some research I believe it is doable . There for finally , for my final project I will be creating a simple trivia game for children using processing and with Arduino I will be using two button for the player to pick from the two option I will provide them with.
Ever since we did the simple example of the ball using Processing and Arduino together, I had the idea of implementing a hockey game using two potentiometers. Unfortunately, I was not able to visit the electronics store during the weekend and so I just decided to make player 2 use the mouse instead. Unlike previous assignments where I keep changing my mind over which idea to implement and what to do, I was pretty decided on my assignment for this week.
References:
I used example 4 from the folder which Aaron provided us with in order to have a proper serial event on Processing which can take in multiple inputs from Arduino and complete the handshake. I also used the example titled Bounce from the Processing application as reference.
Implementation:
I decided to make a class for every single object in order to have much deeper and control and power over what exactly happens in the game. At first, I only had gameOn and !gameOn as conditions for playing or a screen with instructional text. But then I realized that hockey usually involves 7 rounds and there should be some transitional phase between each round which requires some interaction from the players, so I added a situation named roundEnd and functions called display() in each class which show the pucks at the middle and the ball at the very middle and sets their positions there accordingly until the players click anywhere to continue playing, at which point the pucks go back to depending on the potentiometer and mouseX for position. The conditioning for this took some time because there are many factors involved and I need to calculate both scores simultaneously while keeping count of the rounds in order to finish the game at round 7 and declare a winner.
Challenges:
One major problem I faced which I actually didn’t exactly resolve was the collision of the ball with the pucks, where the blocks are wide and very thin so calculating the distance from the middle of the ball to the middle of the block varies greatly from one end to another, and I just took some average distance of collision as part of the equation but sometimes when the ball touches the far end of the block it looks as if it lags and is moving horizontally on the surface of the block before continuing on. I hope I can improve this aspect because I faced similar problems in past assignments when it comes to calculating distance.
I also realized that a player would not really be focusing on changing how dark/light their puck is but rather try to ensure they hit the ball quickly every time, so perhaps the photocell usage was just an extra feature that may not be very necessary or functional, even though it is still a cool effect in the theme of the game.
Improvement:
One thing I improved from the midterm is actually using mousePressed() instead of mouseClicked(), which is more effective when it comes to restarting the game and works better, the other required a particularly long click in order to work.
Here is my perspective as the player (very sad playing this alone and very hard as well):
Here is the actual final game:
Below is the Arduino Code:
//code inspired from example 4
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("0,0");
}
void loop() {
if(Serial.available()>0){
char inByte=Serial.read();
int knobValue = analogRead(A0);
delay(1);
int color = analogRead(A1);
delay(1);
Serial.print(knobValue);
Serial.print(',');
Serial.println(color);
}
}
Below is the Processing Code:
import processing.serial.*;
Serial myPort;
Tab block;
Tab2 block2;
Ball ball;
int rounds = 0;
boolean gameOn = true;
boolean roundEnd = true;
int score1 = 0; //initializing score to 0
int score2 = 0;
PFont f; //f object for all the texts in the game
//inspired from bounce example
class Ball {
int radius = 20; // Width of the shape
float xpos, ypos; // Starting position of shape
float xspeed = 2; // Speed of the shape
float yspeed = 2; // Speed of the shape
int xdirection = 1; // Left or Right
int ydirection = 1; // Top to Bottom
Ball()
{
noStroke();
ellipseMode(CENTER);
// Set the starting position of the shape
xpos = random(radius, width - radius);
ypos = radius;
}
void display() {
xpos = width/2;
ypos = height/2;
ellipse(xpos, ypos, radius, radius);
}
void update(int x, int y)
{
// Update the position of the shape
xpos = xpos + ( xspeed * xdirection );
ypos = ypos + ( yspeed * ydirection );
// Test to see if the shape exceeds the boundaries of the screen
// If it does, reverse its direction by multiplying by -1
if (dist(x, y, xpos, ypos) < radius + 15) {
ydirection *= -1;
}
if (xpos > width-radius || xpos < radius) {
xdirection *= -1;
}
// Draw the shape
fill(255);
ellipse(xpos, ypos, radius, radius);
}
}
class Tab {
int xPos=0;
int yPos = height - 50;
int rectWidth = 80;
int rectHeight = 10;
int colorInput=4;
Tab() {
fill(colorInput - 4, colorInput, random(230,255));
rect(xPos,height - 50, rectWidth, rectHeight);
}
void display() {
fill(colorInput - 4, colorInput, random(230,255));
xPos = width/2;
rect(xPos, yPos, rectWidth, rectHeight);
}
void update() {
fill(colorInput - 4, colorInput, random(230,255));
rect(xPos,yPos, rectWidth, rectHeight);
}
void serialEvent(Serial myPort){
String s=myPort.readStringUntil('\n');
s=trim(s);
if (s!=null){
int values[]=int(split(s,','));
if (values.length==2){
xPos=(int)map(values[0],0,1023, 0 + rectWidth/2 , width - rectWidth/2);
colorInput=(int)map(values[1],0,1023, 150, 10);
}
}
println(xPos);
myPort.write('0');
}
}
class Tab2 {
int xPos= width/2;
int yPos = 50;
int rectWidth = 80;
int rectHeight = 10;
Tab2() {
fill(255, 50, 50);
rect(xPos,height - 50, rectWidth, rectHeight);
}
void display() {
fill(random(230,255), 70, 75);
xPos = width/2;
rect(xPos, yPos, rectWidth, rectHeight);
}
void update() {
fill(random(230,255), 70, 75);
xPos = (int)map(mouseX, 0, width, rectWidth/2, width - rectWidth/2);
rect(xPos,yPos, rectWidth, rectHeight);
}
}
void setup(){
size(600,680);
printArray(Serial.list());
String portname=Serial.list()[2];
println(portname);
myPort = new Serial(this,portname,9600);
myPort.clear();
myPort.bufferUntil('\n');
rectMode(CENTER);
block = new Tab();
block2 = new Tab2();
ball = new Ball();
f = createFont("Raleway-Bold.ttf",72); //aesthetic font that fits teh theme
}
void draw(){
background(0);
if (gameOn && !roundEnd) {
block.serialEvent(myPort);
block.update();
block2.update();
ball.update(block2.xPos,block2.yPos);
ball.update(block.xPos,block.yPos);
if ( rounds == 7) {
gameOn = false;
//roundEnd = false;
}
if (ball.ypos < 59) {
score1++;
rounds++;
roundEnd = true;
}
else if (ball.ypos > height - 59) {
score2++;
rounds++;
roundEnd = true;
}
}
else if (roundEnd && gameOn) {
ball.display();
block.display();
block2.display();
textAlign(CENTER);
String round = "ROUND: ";
String Score1 = "Blue Player: "; //constantly show score at the corner
String Score2 = "Red Player: "; //constantly show score at the corner
textFont(f,20);
fill(255);
text(Score1 + score1, width/2, height/2 - 15); //score text bottom right
text(Score2 + score2, width/2, height/2 - 35); //score text bottom right
textFont(f,24);
text(round + rounds, width/2, height/2 + 35);
}
else {
textAlign(CENTER, CENTER);
textFont(f,40);
//same shade as in the flag
String first;
if (score1 > score2) {
fill(#002868);
first = "BLUE PLAYER WINS!!";
}
else {
fill(#BF0A30);
first = "RED PLAYER WINS!!";
}
text(first, width/2, height/2 - 90);
textFont(f,24);
//same shade as in the flag
fill(255);
String second = "CLICK TO PLAY AGAIN!";
text(second, width/2 - 5, height/2 + 90); //game over text
textFont(f,20);
fill(255);
String third = "Blue Player: ";
String fourth = "Red Player: ";
fill(#002868);
text(third + score1, width/2, height - 20); //score text bottom right
fill(#BF0A30);
text(fourth + score2, width/2, height - 50); //score text bottom right
}
}
void mousePressed() {
if (gameOn == false){ //if mouse is clicked when the game is off, turn it on and reset everything to zero and empty lists
rounds = 0;
score1 = 0;
score2 = 0;
ball.ypos = height/2;
gameOn = true;
}
else if (roundEnd == true) {
gameOn = true;
roundEnd = false;
}
}
This assignment was pretty fun to make and I look forward to diving deeper into the combination of the Arduino and Processing worlds.
For this weeks project I wanted to play with Arduino and create a really low budget version of the famous guitar hero game.
In the game, player has to press a button of the color corresponding to the note which is currently at the strum line. In my game I introduced 3 buttons Red, Green and Blue, which work on the 3 paths of the corresponding colors. When a note falls down to the bottom of the screen the user needs to press the button. Notes appear in random time intervals.
The hardest part of this weeks assignment was picking right time windows for the button reads. Calibrating that to the Arduino module took me quite some time.
Here is my Arduino setup:
Here is me playing the game:
And at last my code:
import processing.serial.*;
Serial myPort;
Note[] notes = new Note[5];
int counter = 0;
int[] positions = {100, 250, 400};
int points = 0;
void setup() {
size(500, 400);
frameRate(30);
textSize(30);
String pName = Serial.list()[2];
myPort = new Serial(this, pName, 9600);
}
void draw() {
drawBackground();
if (frameCount%30 == 0) {
addNote();
}
drawNotes();
}
void serialEvent(Serial myPort) {
String msg = myPort.readStringUntil('\n');
msg = trim(msg);
if (msg != null) {
int btnVals[]=int(split(msg, ';'));
if (btnVals.length == 3) {
if (btnVals[0] == 1) {
checkNote("red");
}
if (btnVals[1] == 1) {
checkNote("green");
}
if (btnVals[2] == 1) {
checkNote("blue");
}
}
}
myPort.write('0');
}
void checkNote(String col) {
int xPos = 0;
switch (col) {
case "red":
xPos = 100;
break;
case "green":
xPos = 250;
break;
case "blue":
xPos = 400;
break;
}
for (int i=0; i<notes.length; i++) {
if (notes[i] != null) {
if (notes[i].x == xPos && notes[i].y > 350) {
notes[i] = null;
points+=1;
}
}
}
}
void drawBackground() {
background(30);
noStroke();
fill(90, 0, 0);
rect(50, 0, 100, 400);
fill(10, 90, 0);
rect(200, 0, 100, 400);
fill(0, 20, 90);
rect(350, 0, 100, 400);
fill(80);
rect(0, 350, 500, 50);
fill(255);
text(points, 5, 30);
}
void drawNotes() {
if (notes != null) {
for (int i=0; i<notes.length; i++) {
if (notes[i] != null) {
notes[i].drawNote();
if (notes[i].y > height) {
notes[i] = null;
points = 0;
}
}
}
}
}
void addNote() {
notes[counter] = new Note(positions[int(random(3))]);
counter = (counter+1)%5;
}
class Note {
int x;
int y = 0;
Note (int xPos) {
x = xPos;
}
void drawNote() {
y += 5;
switch(x) {
case 100:
stroke(255, 0, 0);
break;
case 250:
stroke(0, 255, 0);
break;
case 400:
stroke(0, 0, 255);
break;
}
strokeWeight(50);
point(x, y);
strokeWeight(10);
stroke(255);
ellipse(x, y, 20, 20);
}
}
const int redBtn = 4;
const int greenBtn = 3;
const int blueBtn = 2;
void setup() {
Serial.begin(9600);
Serial.println("0,0");
pinMode(redBtn, INPUT);
pinMode(greenBtn, INPUT);
pinMode(blueBtn, INPUT);
}
void loop() {
if (Serial.available() > 0) {
char inByte = Serial.read();
int red = digitalRead(redBtn);
int green = digitalRead(greenBtn);
int blue = digitalRead(blueBtn);
Serial.print(red);
Serial.print(';');
Serial.print(green);
Serial.print(';');
Serial.println(blue);
}
}
For the final project I want to go with the arcade vibe of Arduino and create a game.
With simple controls in the form of the potentiometer the game will rely on the player controlling a bird, which wants to fly high into the air. On its way, the bird will encounter stormy clouds, which it should avoid at all cost. Also, to reward the courageous bird on its adventure, it will encounter some delicious nuts, which will work as the scoring mechanism for the game.
As the player will collect more and more nuts, the vertical spacing between the clouds will begin to shrink making the game progressively harder and harder.
To add some spice to the game I am also thinking about introducing a BOOST button, which will significantly increase birds flying speed. I think it would be fan to watch the bird dash through the clouds.
The projects seems a bit daunting with all the vertical animations and ways of achieving top quality responsiveness from Arduino buttons but I have two more weeks to figure that out 🙂
Breakout rooms brainstorming brought me a new idea. Instead of speeding things up the button will slow the time and make it easier to move though the clouds. The downside of that will be losing nuts for each second spent in the slow mode.
Also the game difficulty will change basing on the number of nuts collected. Their number will change the speed of downward animation, instead of reducing the vertical spacing of the clouds. That would make the game go faster and faster with each nut collected.
In my project Arduino will provide the input for the bird control. The bird movement will be mapped from the potentiometer, which fits the role perfectly. In addition to that, the slow mode button will provide a mechanism for slowing down vertical transitions.
The processing layer will be responsible for displaying the game as well as the logic. It will take the potentiometer value from Arduino and display the bird on an according position and watch out for the slow mode trigger from the button.
For the Final IM Project, Amina and I decided to work together.
Context 💻
Since we are both in different locations and Zoom is a central element of our life now, we want to incorporate the procedure of joining Zoom meetings but make it fun.
Idea 🎮
The basic idea is to create a musical game that takes input from the laptop keyboard in Processing and puts out sounds and LED signals through Arduino. In our game, the user wants to enter a Zoom meeting. For that, they have to repeat a pattern presented to them. This pattern, we thought, could be presented both through sound and LED output for greater accessibility as some might be more able or comfortable to observe either a sound or a visual pattern. If the pattern is wrong, the user gets to try again. If they repeat the correct pattern, they get to enter the Zoom meeting with congratulation sounds + LED visuals and a welcome message from us. End of game.
Ideas to be determined 🤔
What is the overall story line? Does it end when entering the Zoom meeting?
For the Intro to IM final project, I will be working with Susanne to build an integrated device utilizing Arduino and Processing.
💡 idea
The idea was inspired when Susanne mentioned “something visual about our connection or memory; something that relates us not being in the same location.” So, we decided to recreate the environment of logging into a Zoom meeting and entering the meeting’s password. The key feature of this project is to make the process accessible, by including both sounds and light.
🛠 how it will work
The password will be entered by the user using a computer keyboard to the graphical user interface, and during the typing process, different sounds and lights on Arduino will play. If the password combination is right, a congratulating tone will ring and the user will be let into the meeting.
For this exercise, I wanted to play with colors (yes, I like them a lot) and use different sensory input to change the color of different elements in my Processing sketch. Just exploring different color combinations would make me happy already but I also wanted to add a simple goal to this game which is to manipulate the Arduino sensors in such a way that all objects have the same color so merge in one color blob.
✍🏼Process
I built upon the “05_receiveInArduino” examples that we looked at in class. The potentiometer would be one way of input for color manipulation and I wanted to add the Distance Sensor of our kit for another source of input. For this, I looked up how to use it in the little booklet that came with the kit and also on the Arduino website and used their code. In my Processing sketch, I defined the colors of my elements (two lines of text, ellipse, stroke of ellipse, background) in such a way that they would at some position of the potentiometer all have the same color. Aaron helped me understand the mapping of the distance sensor but I did not yet figure out who to correctly map that input and use it in the Processing sketch for my intention so for now. I will look at this again. The LED was also intended to blink up when the game is solved but for that I would need the distance sensor input so now it is is simply on for 50% of the potentiometer range, and off for the other half. For now, enjoy a very easy to solve version of my game idea 🙂
🎭Outcome
const int trigPin = 11; //connects to the trigger pin on the distance sensor
const int echoPin = 12; //connects to the echo pin on the distance sensor
const int redPin = 3; //pin to control the red LED inside the RGB LED
const int greenPin = 5; //pin to control the green LED inside the RGB LED
const int bluePin = 6; //pin to control the blue LED inside the RGB LED
float sensor2 = 0; //stores the distance measured by the distance sensor
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("0,0");
pinMode(2,OUTPUT);
//code for Distance Sensor taken from Arduino
pinMode(trigPin, OUTPUT); //the trigger pin will output pulses of electricity
pinMode(echoPin, INPUT); //the echo pin will measure the duration of pulses coming back from the distance sensor
}
void loop() {
sensor2 = getDistance(); //variable to store the distance measured by the sensor
sensor2 = map(sensor2, 0, 800, 0, 255);
if(Serial.available()>0){
int inByte=Serial.read();
digitalWrite(2,inByte);
int sensor = analogRead(A0);
delay(1);
int sensor2 = analogRead(A1);
delay(50);
Serial.print(sensor);
Serial.print(',');
Serial.println(sensor2);
}
}
//code for Distance Sensor taken from Arduino
//------------------FUNCTIONS-------------------------------
//RETURNS THE DISTANCE MEASURED BY THE HC-SR04 DISTANCE SENSOR
float getDistance()
{
float echoTime; //variable to store the time it takes for a ping to bounce off an object
float calculatedDistance; //variable to store the distance calculated from the echo time
//send out an ultrasonic pulse that's 10ms long
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
echoTime = pulseIn(echoPin, HIGH); //use the pulsein command to see how long it takes for the
//pulse to bounce back to the sensor
calculatedDistance = echoTime / 148.0; //calculate the distance of the object that reflected the pulse (half the bounce time multiplied by the speed of sound)
return calculatedDistance; //send back the distance that was calculated
}
/* Processing Code
import processing.serial.*;
Serial myPort;
int xPos=0;
int yPos=0;
boolean onOff=false;
void setup() {
size(255, 720);
printArray(Serial.list());
String portname=Serial.list()[5]; //add my port here
println(portname);
myPort = new Serial(this, portname, 9600);
myPort.clear();
myPort.bufferUntil('\n');
}
void draw() {
background(xPos, 0, 255);
strokeWeight(10);
stroke(0, xPos, 255); //eventually: this uses input from sensor2
fill(255, 0, xPos);
ellipse(xPos, height/2, 50, 50);
//instruction text
textSize(32);
text("Align the colors", 5, 30);
fill(0, xPos, 255);
textSize(17);
text("& make everything disappear", 6, 60);
fill(0, xPos*2, 255);
if (xPos >= 126) //eventually: xPos == yPos
onOff=true;
else
onOff=false;
}
void serialEvent(Serial myPort) {
String s=myPort.readStringUntil('\n');
s=trim(s);
if (s!=null) {
int values[]=int(split(s, ','));
if (values.length==2) {
xPos=(int)map(values[0], 0, 1023, 0, width);
//yPos=(int)map(values[1],0,1023,0, height);
yPos=(int)map(values[0], 0, 1023, 0, height);
}
}
myPort.write(int(onOff));
}
*/
I had a really fun time exploring the serial communication between Arduino and Processing this week! My project was inspired by the R, G, B color mapping on Arduino buttons, and without further ado, let me explain what I did.
💡 idea
I wanted to figure out a way, in which I could use my Arduino as a joystick for the Processing game. I started off with some LEDs and a potentiometer, but then decided that I would like to try something different than what we did in class last Wednesday. After that, I wired three buttons on the breadboard, and the colors of the buttons immediately reminded me of the (R, G, B) color mapping. I decided to create a movement game and use my buttons as a joystick for moving whatever I have in my Processing console.
When a player starts the Processing sketch, they will see a rectangle on the console, and whenever each button is pressed, the rectangle changes color and moves to a particular side of the screen. The player’s score increments if the rectangle “hits” the side of the screen.
🛠 process
One of the main challenges while implementing this game was to figure out a way to transfer multiple serial communication bits into Processing. At first, I thought I would create an array of bits that occur while pressing the buttons. However, as I was exploring this idea it seemed like I was overcomplicating it, and then I just tried sending a different type of serial message each time a different button is pressed. For example, if the red button is pressed, I send “1”; if the blue one is pressed, I send “2”, and so on.
After reading this serial communication from my Processing, I created a boolean variable to track which button is pressed. For each boolean variable, I then created corresponding code lines to run throughout the game to move the rectangle. When the rectangle reaches the end of the screen, it reappears on the console, and the game continues until they eventually get tired of playing 😅. Right now, there is no way to stop or restart the game without closing the program, but it could be something to think about as a next step.
🎲 demo
Arduino code:
int buttonR = 2;
int buttonB = 4;
int buttonG = 7;
int prevRState = 0;
int prevGState = 0;
int prevBState = 0;
void setup() {
// put your setup code here, to run once:
pinMode(buttonR, INPUT);
pinMode(buttonG, INPUT);
pinMode(buttonB, INPUT);
Serial.begin(9600);
}
void loop() {
// getting digital communication from buttons
int buttonRState = digitalRead(buttonR);
int buttonGState = digitalRead(buttonG);
int buttonBState = digitalRead(buttonB);
// read if the buttons are pressed
int valueR = digitalRead(buttonR);
int valueG = digitalRead(buttonG);
int valueB = digitalRead(buttonB);
// output for debugging
Serial.print(valueR);
Serial.print(valueG);
Serial.print(valueB);
if (buttonRState == 1 && prevRState == LOW){
// send values if buttons are pressed
Serial.write(valueR);
}
if (buttonGState == 1 && prevGState == LOW){
// send values if buttons are pressed
Serial.write(valueG+1);
}
if (buttonBState == 1 && prevBState == LOW){
// send values if buttons are pressed
Serial.write(valueB+2);
}
// track button states
prevRState = buttonRState;
prevGState = buttonGState;
prevBState = buttonBState;
}
Processing code:
import processing.serial.*; // importing from library
Serial port; // creating a serial port object
int numBtns = 3; // number of buttons
int locX, locY; // position of each rectangle
int rectW, rectH; // width and height of each rectangle
int value = 0; // passed value
boolean isRed, isGreen, isBlue = false; // keep track of colors
int numCollide; // keep track of collisions
void setup(){
size(500, 500);
rectMode(CENTER);
locX = 250;
locY = 250;
rectW = 100;
rectH = 100;
numCollide = 0;
//printArray(Serial.list()); // debugging
port = new Serial(this, Serial.list()[1], 9600); // initializing the port
}
void draw(){
background(255);
// initializing the game
rect(locX, locY, rectW, rectH);
displayScore();
// green mode
if (isGreen == true){
rect(8, 250, rectW-80, height);
locX-=5;
}
// red mode
if (isRed == true){
rect(490, 250, rectW-80, height);
locX+=5;
}
// blue mode
if (isBlue == true){
rect(250, 10, width, rectH-80);
locY-=5;
}
// start again
reStart();
}
void serialEvent(Serial port){
// reading from the port
value = port.read();
// change to red
if (value == 1){
fill(255, 0, 0);
isRed = true;
isBlue = false;
isGreen = false;
}
/// change to green
if (value == 2){
fill(0, 255, 0);
isRed = false;
isBlue = false;
isGreen = true;
}
// change to blue
if (value == 3){
fill(0, 0, 255);
isRed = false;
isBlue = true;
isGreen = false;
}
}
// restart each time the rectangle is caught
void reStart(){
if (locX==-rectW || locY == -rectH || locX == width+rectW){
numCollide++;
locX = 250;
locY = 250;
}
}
// display the instructions and the score
void displayScore(){
textAlign(CENTER);
push();
textSize(16);
fill(0);
text("Press any arduino button to start!", width/2, height-100);
pop();
push();
textSize(32);
fill(0);
text("Score: " + numCollide, width/2, height-50);
pop();
}
Being named Beethoven, I had to live up to my name somehow, so I decided to create a (very) mini piano.
What I had in mind was a button that acts as a switch, a potentiometer that affects the frequency of the notes, and seven buttons to be clicked as the basic fundamental notes (C4, D4, E4, F4, G4, A4, B4). So this is how I imagined my circuit to look like and it actually ended up being the same exact thing.
Interestingly, for this assignment, I faced challenges only in code and not in wiring at all. So I just kept changing my strategy of coding in order to suit what I was building.
So in my first trial, I used if conditions to play the notes according to the corresponding button. I made the potentiometer be like some kind of volume changer. When I tested the potentiometer only, it changed the volume from 0 to 255 perfectly and worked well using analogWrite().
I would write analogWrite(piezo, pwm) , where pwm is the mapped value of knobValue from 0 to 125.
When I used the buttons only and the function tone(), they worked perfectly fine and the switch worked too.
I would write tone(piezo, notes[i], 100).
But when I merged the two in code, it was weird. The switch button almost did not work, the buttons wouldn’t work if the switch was off, but the buzzer still produced some background noise all the time. In addition, the potentiometer would only turn on the keys after a certain point, and turn them before that, there was no spectrum but rather as if it was a switch. The circuit would only be silenced if the potentiometer was at 0 and while one of the keys was held.
In my second attempt, I tried to separate analogWrite() and tone() because I realized the two cannot work simultaneously on the same output device. So instead of changing volume I changed the frequency by keeping the range 0 to 1023 mapped into 0 to 100 and multiplying some of the keys by the mapped value (specifically the last button) and adding the value to the rest as you change the potentiometer.
But then I just felt like multiplying the frequencies by any number just produces an 8-bit very annoying sound, and adding the same number to them makes it actually hard to differentiate between them because they are all already not equal and have increasing values which differ by around 32 Hz. So I decided to dismiss the idea of changing the volume using the potentiometer like in trial 1 and stick to changing frequency like trial 2. I decided to make the mapping in range 0 to 32 (unlike trial 2) because that’s the average difference between them, and then I would add pwm to the first, 2*pwm to the second, 3*pwm to the third, … and so on, to keep the difference between them constant. I also chose a relatively low number so the tones could still be identifiable and fit in an instrument that can be bearable. I have to point out that the piezo that I have produces low quality sounds in any case so the videos might be a bit noisy.
The piano turned out to be not very enjoyable to be honest, but with more trials and better equipment, it could be improved and shaped into a more realistic one.
The code I used for this assignment:
#include "pitches.h"
int button = 2; //button pin
int key1 = 5;
int key2 = 6;
int key3 = 7;
int key4 = 8;
int key5 = 9;
int key6 = 10;
int key7 = 11;
int notes[7] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4}; //standard notes
int piezo = 3;
bool prevButtonState = LOW; //initializing button to be unpressed
bool gameOn = false;
int knob = A0; //pin of potentiometer
void setup() {
pinMode(button, INPUT); //button initialized as input
pinMode(key1, INPUT); //button initialized as input
pinMode(key2, INPUT); //button initialized as input
pinMode(key3, INPUT); //button initialized as input
pinMode(key4, INPUT); //button initialized as input
pinMode(key5, INPUT); //button initialized as input
pinMode(key6, INPUT); //button initialized as input
pinMode(key7, INPUT); //button initialized as input, these are the piano keys
pinMode(piezo, OUTPUT); //buzzer is output
Serial.begin(9600);
}
void loop() {
int buttonState = digitalRead(button); //storing reading from button
Serial.println(buttonState);
if (buttonState == HIGH && prevButtonState == LOW) { //if button is clicked change the piano states to their opposites
gameOn = !gameOn;
}
if (gameOn == true) { //if the piano were previously off then were turned on by button
int knobValue = analogRead(knob); //store reading from photocell
int button1 = digitalRead(key1);
int button2 = digitalRead(key2);
int button3 = digitalRead(key3);
int button4 = digitalRead(key4);
int button5 = digitalRead(key5);
int button6 = digitalRead(key6);
int button7 = digitalRead(key7); //read current values from buttons/keys
byte pwm = map(knobValue, 0, 1023, 0, 32); //mapping analog values into range of average difference between the standard notes
Serial.println(knobValue);
if (button1 == HIGH) { //if button is pressed
tone(piezo, notes[0] + pwm, 100); //add to the standard frequency the corresponding value from potentiometer
}
if (button2 == HIGH) {
tone(piezo, notes[1] + 2*pwm, 100); //add twice the value from potentiometer to frequency
}
if (button3 == HIGH) {
tone(piezo, notes[2] + 3*pwm, 100); //add 3 times the values from potentiometer to frequency
}
if (button4 == HIGH) {
tone(piezo, notes[3] + 4*pwm, 100); //add 4 times the values from potentiometer to frequency
}
if (button5 == HIGH) {
tone(piezo, notes[4] + 5*pwm, 100); // add 5 times the values from potentiometer to frequency
}
if (button6 == HIGH) {
tone(piezo, notes[5] + 6*pwm, 100); //add 6 times the values from potentiometer to frequency
}
if (button7 == HIGH) {
tone(piezo, notes[6] + 7*pwm, 100); //add 7 times the values from potentiometer to frequency
}
if (button1 == LOW && button2 == LOW && button3 == LOW && button4 == LOW && button5 == LOW && button6 == LOW && button7 == LOW){
analogWrite(piezo, 255); //if none of the buttons is pressed then make buzzer make no noise
}
delay(10);
}
else {
analogWrite(piezo, 255); //if the switch is off turn buzzer off
}
prevButtonState = buttonState; //update prevButtonState in each loop
}