Final Project Proposal

For my final project, I’m going to build something for this Zoom era. I get a lot of migraines and sometimes just need to put my head down during classes/meetings…but, I don’t want to fall asleep!

This contraption aims to detect when the user has put their head down and gently remind them to stay present. The user also will have the option to display the text of what is being said.

The Arduino program:

Input: when has the user put their head down. I will use either an ultrasonic sensor or use this Capacitor Sensor library to create a sensor using foil inside the pillow.

Output: gentle sound using piezo buzzer depending on input in Processing program, also sends signal to Processing program that user has put head down

(I would also like to explore creating vibrations as output but am not sure how to do this)

 

The Processing program (p5.js):

Input: signal from Arduino that user has put head down,  speech of class/meeting, time interval user wants to be reminded at

Output: display text of class/meeting, sends signal to Arduino of when to create sound/vibrations

 

Considerations:

The p5 program will have an alert: the user should only display the transcript if there is consent from the other participants in the Zoom call (ex: meeting is being recorded). The program will also not save the text anywhere and will be cleared from the screen after a certain time.

The P5 speech library I wanted to use (Thanks Aaron for the rec!) seems to be better than expected at recognizing names that aren’t typically used in English (it recognized a lot of my friends’ names and mine when I experimented), but it will definitely not be perfect, so I’m not sure whether to proceed with the name recognition alarm feature.

Arduino + Processing Game [EXTRA CREDIT]

Project Outline

So for this project, we will be using an Arduino Uno Board and an SR-04 Ultrasonic sensor, a breadboard, and a few wires. So this game is built upon the midterm game that I have created previously, Drowning Diver. But this time around, the game is controlled with an ultrasonic sensor that feels the distance between whatever is put in front of it. When sensor is covered it goes up, when user puts his fingers away that cover sensor the diver goes down and drowns))

To be honest, I really wanted to make a game using screen. Last lesson when we were having a group discussion of our ideas, Alima has mentioned that we have a so-called screen that can display on it. That was the time when I got so excited to working with it, but immediately that idea backfired.

PROCESSING CODE

PImage wall;
PImage character;

import processing.serial.*;
int DistanceUltra;
int IncomingDistance;
Serial myPort;
String DataIn;
Pipe p1 = new Pipe();
Pipe p2 = new Pipe();
Pipe p3 = new Pipe();
 
//bird height and width location
float birdy = 46;
float birdx = 56;
float gravity = 5;
//float jumpForce = 15;
 
//the speed of the pipes
int speed;
 
//score and game state
boolean gameOver = false;
int score = 0;
int highscore = 0;
 
int point = 1;
 
color birdColor = color(255, 204, 0);
 
 
void setup(){
  size(800,400);
  wall=loadImage("underwater.png");
  character=loadImage("scuba.png");
  p1.x = width + 80;
  p2.x = width + 200;
  p3.x = width + 400;
  printArray(Serial.list());
  String portname=Serial.list()[2];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.bufferUntil(10);
}
void serialEvent (Serial myPort){
DataIn = myPort.readString();
println(DataIn);
IncomingDistance = int(trim(DataIn));
println("incoming distance="+IncomingDistance);
if (IncomingDistance>1 && IncomingDistance<100 ) { DistanceUltra = IncomingDistance; //save the value only if its in the range 1 to 100 } }
}
}
 
void draw(){
 
  background(wall);
  p1.pipe();
  p2.pipe();
  p3.pipe();
 
  fill(birdColor);
  ellipse(birdx, birdy, 55,55);
 // birdy += gravity;
  play();
  success(p1);
  success(p2);
  success(p3);
 
  if (IncomingDistance>10)
  {
    //birdy -= jumpForce;
    birdy -= gravity;
  }    
  else
  {
    birdy += gravity;
  }
  
}
 
 
void play(){
 
  if(gameOver == false)
  {
    speed = 2;
    p1.x -= speed;
    p2.x -= speed;
    p3.x -= speed;
   
    textSize(24);
    fill(255,255,255);
    text(score, width/2, 30);  
  }
 
  if(gameOver == true)
  {
    speed = 0;
    p1.x -= speed;
    p2.x -= speed;
    p3.x -= speed;
   
    if( highscore < score)
    {
       highscore = score;
    }
   
    textSize(16);
    fill(0, 102, 153);
    textAlign(CENTER);
    text("Click : Play Again", width/2, height/2);
    text("Score: " + score, width/2, height/2 - 20);
    text("High-Score: " + highscore, width/2, height/2 - 40);
   
    if (mousePressed)
    {
       delay(900);
       score = 0;
       gameOver = false;
       birdy = 100;
       birdx = 56;
       p1.x = width + 50;
       p2.x = width + 220;
       p3.x = width + 370;
       p1.top = random(height/2);
       p1.bottom = random(height/2);
       p2.top = random(height/2);
       p2.bottom = random(height/2);
       p3.top = random(height/2);
       p3.bottom = random(height/2);
 
    }  
  }
 
}
 
void success(Pipe test){
 
  if(birdy < test.top || birdy > height - test.bottom)
  {
    if(birdx > test.x && birdx < test.x + test.w)
    {
      gameOver = true;
    }
  }
}
class Pipe
{
  float top = random(height/3 + 200);
  float bottom = random(height/3 +200);
 
 
  float x = width + 150;
  float w = 70;
  color pipeColor = color(0, 255, 0);
 
  void pipe()
  {
    fill(pipeColor);
    rect(x, 0, w, top);
    rect(x, height-bottom, w, bottom);
   
    if(x < -100)
    {
     score += point;
     x = width;
     top = random(height/2);
     bottom = random(height/2);
    }
 
   
  }
 
 
}

ARDUINO CODE

const int trigPin=11; 
int echoPin=10; 
int safezone=10; 
//int dpin=13;
void setup() 
{
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
//pinMode(dpin,OUTPUT);
//digitalWrite(dpin,LOW);
Serial.begin(9600);
}
void loop()
{
long duration,cm; //DECLARE VARIABLES TO STORE SENSOR O/P
digitalWrite(trigPin,LOW); //MAKE THE TRIG PIN LOW
delayMicroseconds(2); //WAIT FOR FEW MICROSECONDS
digitalWrite(trigPin,HIGH); //NOW SET THE TRIG PIN
delayMicroseconds(5); //WAIT FOR FEW MICROSECONDS UNTIL THE TRIG PULSE IS SENT
digitalWrite(trigPin,LOW); //MAKE THE TRIG PIN LOW AGAIN
duration=pulseIn(echoPin,HIGH); //MAKE ECHO PIN HIGH AND STORE THE BOUNCED PULSE IN VARIABLE DURATION
cm=microsecondsToCentimeters(duration); 
long inch= cm/2.54;
//if(cm<safezone) 
//{
//digitalWrite(dpin,HIGH);
Serial.println(cm);
//delay(500);
//digitalWrite(dpin,LOW);
//}
}
long microsecondsToCentimeters(long microseconds) //SPEED OF SOUND IS 29 uSEC PER CM
{
return microseconds/29/2; //THE PULSE TRAVELS FROM THE SENSOR AND AGAIN COMES BACK SO WE DIVIDE IT BY 2 TO TAKE ONLY HALF OF THE TOTAL DISTANCE
}

SCHEMATICS

VIDEO DEMONSTRATION

Space Shooter Game – Extra Credit

For this extra credit project, I wanted to test my knowledge of the handshake between processing and arduino and so I came up with a space shooter game. It is a pretty basic game in which the space ship has to shoot the incoming meteoroids and if it shoots 10 of them the game is over.

 

Processing

The processing part is basically the interface of the game, which includes the start screen, the space ship, the asteroid and the whole shooting mechanism and also the end screen.

The game starts with the start screen in which the player clicks within a box to start playing.

The code basically spawns random sizes of asteroids, that fall at random speeds too. If the player is able to shoot 10 asteroids, the game is over and the player is prompted to either restart the game or click on game over to return to the start screen.

Processing Code:

import processing.serial.*;
Serial myPort;
ArrayList<Asteroid> asteroids = new ArrayList<Asteroid>(); //gives the list of asteroids
Player player; //player object
boolean shoot = false; // ensures that the player only shoots when commanded
ArrayList<Player.Bullet> bullets = new ArrayList<Player.Bullet>(); //bullet list
float timer = 0;
float timerlength  = 4000;
boolean game_over = false; 
boolean start = false; 
int count = 0; 
int currentButtonState = 0;
int prevButtonState = 0;
float mover = width/2; 

void setup()
{
  size(1280, 960);
  
  imageMode(CENTER);
  //asteroids.add(new Asteroid(random(width*0.25, width*0.75), 0, int(random(1, 3)))); //initialising the list of asteroids to spawn in between the roads of the game
  player = new Player();
  printArray(Serial.list());
  String portname=Serial.list()[6];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
  
}

void draw()

{
  PImage bg;  
  bg = loadImage("space.jpeg");
  bg.resize(int(width),int(height));
  background(bg); //background is the top down view of a road
  if (start == false)
  {
    textAlign(BASELINE);
  rectMode(CENTER);
  fill(255);
  stroke(230,153,0);
  rect(width/2,height/2,700,500,10);
  rect(width/2, height/2,680,480,10);
  
  fill(0);
  textSize(50); 
  text("Welcome", 480, 410);   
  fill(255);
  rect(625,580,600,100,10);
  fill(0);
  text("Click to Play", 420, 610);
  if ((mouseX >= 325 && mouseX <= 925) && (mouseY >= 530 && mouseY <= 630) && (mousePressed == true))
   {
     start = true;
   }
  }
  
  else{  
  if(game_over == false)
  {
   
    Player_Mechanics();
    Asteroid_Mechanics(); 
    Shoot();
    Mover();
    
    if( millis() > timer)
    {
      asteroids.add(new Asteroid(random(width*0.25, width*0.75), 0, int(random(1, 3)))); //initialising the list of asteroids to spawn 
      timerlength = random(1000,5000);
      timer = millis() + timerlength;
    }
  }
  
  else{
   textAlign(BASELINE);
  rectMode(CENTER);
  fill(255);
  stroke(230,153,0);  
  rect(width/2,height/2,700,500,10);
  rect(width/2, height/2,680,480,10);
  
  fill(0);
  textSize(50); 
  stroke(0);
  text("Game Over!", 420, 410);   
  fill(255);
  rect(625,580,600,100,10);
  fill(0);
  text("Restart", 420, 610);
  if ((mouseX >= 325 && mouseX <= 925) && (mouseY >= 530 && mouseY <= 630) && (mousePressed == true))
   {
     game_over = false;
     count = 0; 
   }
   
   if ((mouseX >= 325 && mouseX <= 925) && (mouseY >= 330 && mouseY <= 430) && (mousePressed == true))
   {
     start = false;
   }
   
  }
  }
}

void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
    int values[]=int(split(s,','));
    if (values.length==3){
      currentButtonState=(int)values[0];
      prevButtonState=(int)values[1];
      mover = map(values[2], 0, 1023, player.size/2, width-player.size/2);
    }
  }
  myPort.write("\n");
}

void Player_Mechanics()
{
  
  player.drawPlayer();  //draws the Player on Screen
  
  for(int i =0; i< bullets.size(); i++)
  {
    
    bullets.get(i).draw_Bullet();
    bullets.get(i).shoot_Bullet();  //if bullets are present, draws them and shoots them
    if(bullets.get(i).bullet_posY_1 < 0 )
      bullets.remove(i); //removes the bullet once they are out of frame
  }
  

}


void Asteroid_Mechanics()
{
  for (int i = 0; i < asteroids.size(); i++)
  {   
    asteroids.get(i).drawAsteroid();
    asteroids.get(i).moveAsteroid(); //draws and moves asteroids on screen
    if(asteroids.get(i).posY > height + asteroids.get(i).size)
      asteroids.remove(i);  //removes the asteroids once they are out of frame
    if( bullets.size() > 0 && asteroids.size() > 0 )
    {
      for(int j=0; j<bullets.size(); j++)
      {
        if( bullets.size() > 0 && asteroids.size() > 0 )
        {
          if(asteroids.get(i).vicinty_check(bullets.get(j).bullet_posX,bullets.get(j).bullet_posY_2))
            {
              asteroids.remove(i); //destroys the asteroid and removes it once bullet touches it
              count++;
            }
        }
      }
    }
  }
  if (count == 10){
    game_over = true;
  }   
}

void keyPressed()
{
  if (key == ' ')
  {
    asteroids.add(new Asteroid(random(width*0.25, width*0.75), 0, int(random(1, 3)))); //spawns an asteroid
  }

  if (key == 'a')
  {
    player.moveLeft(); //player goes left
  }

  if (key == 'd')
  {
    player.moveRight(); //player goes right
  }
  
  if (key == 'f')
  {
    bullets.add(player.new Bullet(0));  //shoots bullets
  }
}

void Shoot()
{
  if (currentButtonState == 1 && prevButtonState == 0) {
    bullets.add(player.new Bullet(0));     
    println("cheeky");
  }
}


void Mover()
{
  player.posX = mover;
}
class Asteroid {

  float posX;
  float posY;
  int speed = (int)random(2,6);
  int size;
  PImage asteroid;




  Asteroid(float x, float y, int s)
  {
    posX = x;
    posY = y;
    size = s*100;
    asteroid = loadImage("asteroid_brown.png");
    imageMode(CENTER);
  }

  void drawAsteroid()
  {

    asteroid.resize(size, 0);
    image(asteroid, posX, posY);  //resizes and draws the asteroid
  }

  void moveAsteroid()
  {
    posY += speed;  //moves the asteroid
  }

  boolean vicinty_check(float x, float y)
  {
    if ((x < posX+size/2 && x > posX-size/2) && (y < posY+size/2 && y > posY-size/2))  //checks if anything exists in the vicintiy of the asteroid's body
      return true;
    else
      return false;
  }
}
class Player {

  public float posX = width/2;  
  public float posY = height-100;
  PImage player;  
  int movement=20;
  int size =100;


  Player()
  {

    player = loadImage("Spaceship_tut.png");
    imageMode(CENTER);
  }



  void drawPlayer()
  {
    player.resize(size, 0);
    pushMatrix();
    translate(posX, posY);
    //rotate(radians(270));
    image(player, 0, 0);
    popMatrix(); //resizes and rotates the image of the player on screen so that it is appropriate for the game
  }

  void moveLeft()
  {
    
    if (posX > size/2)
      posX -= movement; //player moves left
  }

  void moveRight()
  {
    
    if (posX < width-size/2)
      posX += movement; //player moves right
  }


  class Bullet {    //nested bullet class in player class

    float  bullet_posX = posX ;
    float  bullet_posY_1 = posY - size/2; 
    float  bullet_size = size * 0.1; 
    float  bullet_posY_2 = posY - size/2 - bullet_size; 
    int bullet_speed = 20; 


    Bullet(float y)
    {
      bullet_posY_1 -= y;
      bullet_posY_2 -= y;    //assigns intial position to bullet
    } 
    void draw_Bullet()
    {
      stroke(102,255,102);
      strokeWeight(6);
      line(bullet_posX, bullet_posY_1, bullet_posX, bullet_posY_2);  //draws a line for a bullet
    } 

    void shoot_Bullet()  

    {
      bullet_posY_1 -= bullet_speed;
      bullet_posY_2 -= bullet_speed;  //moves bullet
    }
  }
}

 

Game Display

Arduino

The Arduino part involves the controls for the game in which the potentiometer is used to move the spaceship around and the push button is used to shoot the missiles from the spaceship.

 

Arduino Code:

int buttonPin = 2;
int prevButtonState = LOW;

void setup() {
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
  Serial.println("0,0");
}

 void loop() {
  while (Serial.available()) {
    if (Serial.read() == '\n') {
      int currentButtonState = digitalRead(buttonPin);
      delay(1);      
      Serial.print(currentButtonState);
      Serial.print(',');
      Serial.print(prevButtonState);
      Serial.print(',');      
      prevButtonState = currentButtonState;
      int mover = analogRead(A0);
      delay(1);
      Serial.println(mover);
    }
  }
  
  //Serial.println(sensor);

}

 

Circuit:

Arduino Circuit

Videos:

This is the video of me showing the way the game works:

This is a video of me actually playing the game:

Difficulties:

In certain instances, I felt that the button was not responding in the way I wanted it to but I believe that is primarily because I hadn’t plugged it well or the communication of information was slow.

Overall:

This project was actually really fun and it made me feel so cool to create my own joystick for my game. This has also motivated me quite a lot for my final project which I am really looking forward to!

Extra Arduino Game

Assignment:

This week we were given the option of creating a game with the Arduino and I decided to continue with my favorite Processing game thus far, my F1 simulator. I wanted to make a controller that would be integrated into the game.

 

Game Controller:

There are three main inputs in a car (a simplified automatic one anyways), steering, gas, and acceleration. My game already had these inputs but steering was in essence binary (full left, neutral, full right). I decided that analog input could make for much more fun steering and in addition to gas/brake buttons I could make a F1 car controller.

For the steering I used the potentiometer. I had to rework all my code for how the car was steered as it was no longer left or right, but rather any value from full left to full right and anywhere in-between. I ended up checking which way the potentiometer was facing and mapping the annual acceleration of the car off of this.

I also added a brake and gas button. These were super easy to implement as they behaved exactly the same as if I was pressing the up or down arrow in the keyboard controls so all I had to was change to binary values if they were on or off.

Finally I wanted something a bit extra than just inputs, also outputs that could make the player feel more like they were in a car. I decided to add two LEDs, a green one that would light up when pressing the gas, and a red one that would light up when braking, or flash when the car crashed like hazard lights. This allowed me to try the no delay blinking code as well.

Circuit

Code

Arduino Code

const int brakeLed = 5;
const int forwardLed = 4;
const int forwardButton = 2;
const int brakeButton = 3;
const int sensorPin = A0;

int forward = 0;
int brake = 0;
int crash = 0;
long timer = 0;
int timerLength = 500;
bool onOff = false;

void setup() {
  Serial.begin(9600);
  Serial.println("0,0");
  pinMode(brakeLed, OUTPUT);
  pinMode(forwardLed, OUTPUT);
  pinMode(forwardButton, INPUT);
  pinMode(brakeButton, INPUT);
}

void loop() {
  while (Serial.available()) {
    forward = Serial.parseInt();
    brake = Serial.parseInt();
    crash = Serial.parseInt();
    if (Serial.read() == '\n') {
      if (crash) {
        if (millis() > timer) {
          onOff = !onOff;
          digitalWrite(brakeLed, onOff);
        digitalWrite(forwardLed, LOW);
          timer = millis() + timerLength;
        }
      }
      else{
        digitalWrite(forwardLed, forward);
        digitalWrite(brakeLed, brake);
      }
      int forwardToggle = digitalRead(forwardButton);
      delay(1);
      int brakeToggle = digitalRead(brakeButton);
      delay(1);
      int steeringInput = analogRead(sensorPin);
      delay(1);
      Serial.print(forwardToggle);
      Serial.print(',');
      Serial.print(brakeToggle);
      Serial.print(',');
      Serial.println(steeringInput);
    }
  }
}

Processing Code

import processing.sound.*;

//======= Global variables ========
int gameMode = 0; //0 is main menu, 1 select your car, 2 running game, 3 crash, 4 controls menu, 5 credits
Team teams[] = new Team[10];
int teamSelector = 0;  //Which team from array is selected
int[][] teamDict = {{7, 0, 7, 0, 0}, {8, 1, 8, 0, 1}, {5, 2, 5, 0, 2}, {4, 3, 4, 0, 3}, {0, 4, 0, 0, 4}, {2, 5, 2, 1, 0}, {1, 6, 1, 1, 1}, {6, 7, 6, 1, 2}, {9, 8, 9, 1, 3}, {3, 9, 3, 1, 4}}; //Dictonary containing index of car sprite, associated team image sprite index, team name index, menu row, menu col

//====== Team Selection Menu Variables
PImage teamMenuImg;


//====== Trak Menu Variables
//  PImage track[][] = new PImage[10][10];  //For tile system
//float tileWidth = 2560;  //For tile system
PImage map;
float trackScale = 1; //What percent of original size should track be drawn

//====== Main Game Variables
float rotation = PI;  //Current angle
float speed = 0;  //Current speed
float maxSpeed = 500;  //Max speed on the track
float sandMaxSpeed = 20;  //Max speed off the track
float posX = -4886.6123;  //0,0 is top left of track , values increase negative as they are reversed
float posY = -1254.3951;

float acceleration = 5;  //How fast the car speeds up on track
float sandAcceleration = 1;  //How fast the car speeds up in sand
float brakeDeacceleration = 10;  //How quick the car stops when braking on track
float coastDeacceleration = 2;  //How quick the car stops when no power
float sandDeacceleration = 15;  //How quick the car stops in sand
float angularAcceleration = PI/20;  //How fast the car turns
boolean reverse = false;

float carScale = 0.3; //What percent of original size should car be drawn

//Keyboard inputs
boolean forward = false;
boolean brake = false;
boolean left = false;
boolean right = false;

//Sound
SoundFile accSound;
float accSoundAmp = 0;
float soundRate = 0.5;

//Timing
int passedTime;  //How long has passed since saved time mark
int savedTime;  //Savea time to start timer
boolean activeTimer = false; //Set to false, becomes active when crossing start line or false if reversed over
int bestTime = -1;

//Menu files
PImage controls;
PImage credits;

//Main menu variables  
  int numButtons = 3;
  int activeButton = 0; // 0 for start, 1 for controls, 2 for credits
  int buttonWidth = 200;
  int buttonHeight = 100;
  int buttonSpacing = 50;
  int buttonYOffset = 100;
  String buttonContent[] = {"Start Game","Controls","Credits"};
  float buttonX;
  float buttonY;
  
//Arduino game control variables
import processing.serial.*;
Serial myPort;
boolean crash = false;

void setup() {
  fullScreen();

  //Set up the team array
  //=======================================================================================
  PImage[] carSprites;
  PImage[] teamSprites;
  String[] nameArray = {"McLaren F1 Team", 
    "Scuderia AlphaTauri Honda", 
    "Mercedes-AMG Petronas F1 Team", 
    "ROKiT Williams Racing", 
    "Haas F1 Team", 
    "BWT Racing Point F1 Team", 
    "Scuderia Ferrari", 
    "Alfa Romeo Racing ORLEN", 
    "Aston Martin Red Bull Racing", 
    "Renault F1 Team"
  };
  //Alfa Romeo, Red Bull, Racing Point, Haas, Mclaren, Mercedes, AlphaTauri, Ferrari, Renault, Williams

  //Set sprite sheets
  carSprites = getCarSpriteSheet("SpriteSheetCars.png");  //Load the car sprite sheet into sprites
  teamSprites = getTeamSpriteSheet("Teams.png");  //Load the team sprite sheet into sprites

  //Set teams array with appropiate info
  for (int i = 0; i < 10; i++) {
    Team newTeam = new Team();
    newTeam.setName(nameArray[teamDict[i][2]]);  //Set team name
    newTeam.setCarImg(carSprites[teamDict[i][0]]);  //Set team img
    newTeam.setTeamImg(teamSprites[teamDict[i][1]]);  //Set team car img
    teams[i] = newTeam;
  }

  //=======================================================================================

  //Load menu imgs
  teamMenuImg = loadImage("Teams.png");
  controls = loadImage("Controls.png");
  credits = loadImage("Credits.png");

  //=======================================================================================

  //Load map
  map = loadImage("Track.png");

  //=======================================================================================
  //Load sound
  accSound = new SoundFile(this, "acc.wav");
  accSound.loop();
  accSound.amp(accSoundAmp);
  accSound.rate(soundRate);
  
  //Start lap timer
  savedTime = millis();
  
  //Start serial communication with controller
  String portname=Serial.list()[1];
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}

void draw() {
  //Main Gamemode Control selector
  switch(gameMode) {
  case 0:
    mainMenu();
    break;
  case 1:
    teamMenu();
    break;
  case 2:
    runGame();
    break;
  case 3:
    crash();
    break;
  case 4:
    controls();
    break;
  case 5:
    credits();
    break;
  }
}


//When all game cariables need to be reset to start status
void resetVariables(){
  accSound.amp(0);
  forward = brake = right = left = false;
  activeTimer = false;
  speed = 0;
  gameMode = 0;
  posX = -4886.6123;  //0,0 is top left of track , values increase negative as they are reversed
  posY = -1254.3951;
  rotation = PI;
  crash = false;
}


void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
    int values[]=int(split(s,','));
    if (values.length==3){
      if(values[0] == 1 && values[1] == 1){
        forward = false;
        brake = false;
      }
      else if (values[0] == 1){
        forward = true;
      }
      else if (values[1] == 1){
        brake = true;
      }
      else if (values[0] == 0 && values[1] == 0){
        forward = false;
        brake = false;
      }
      
      
      int steering = values[2];
      //Turn left
      if(steering > 1023/2){
        left = true;
        right = false;
        angularAcceleration = map(values[2],1023/2,1023,0, PI/20);
      }
      else if(steering < 1023/2){
        left = false;
        right = true;
        angularAcceleration = map(values[2],1023/2,0,0, PI/20);
      }
    }
  }
  println(crash);
  myPort.write(int(forward)+","+int(brake)+","+int(crash)+"\n");
}

 

Results

[Week 12] Final project proposal – Ngoc and Maaz

Game concept

In our previous post, Maaz and I mentioned that we would be using Processing and Arduino together to make a game for our final project which would be similar to Tetris. However, both of us were not very satisfied with how we were using the sensors in our game. We thought we could find some ways to better utilize the Arduino components. Additionally, after the discussion session on Monday, we were pretty sure that we had to make tweaks to the game play.

We now have a new version of our game. This version is very different from Tetris but it uses most of the sensors in the same way as the previous version did. The distance sensor continues to be the most important resistor, while we have added a few new features. This version is an NYUAD-themed game, in which the player playing the game sees certain objects falling down the screen. These objects will be of two categories: objects which the player should catch and objects which the player should avoid. The player controls the game using the breadboard which has the distance sensor mounted on it (the entire things acts as a “remote control”). Towards the right and left of the remote control will be a frame (made of cardboard for instance). The two sides of this frame represent the endpoints of the game screen, and they help us determine how far the distance sensor (and hence the remote control) is from one end of the screen. Using this “remote control”, the player’s position can also be displayed on the screen for the player to figure out how close/far away they are from objects that are to be caught/avoided.

The ground rules of the game are as the following:

  • Just like in the previous version of our game, this version will have multiple levels of varying difficulty. We plan to have four levels corresponding to four academic years, with each succeeding level harder than the previous one.
  • The player has to maintain two metrics of performances: academic performance and well-being. There are certain objects that are beneficial and objects that are harmful to a performance. You need to catch the good objects (which will increase your performance) and avoid the bad ones (which will decrease your performance).
  • Initially, both performances start at 50% and you need to take them both to 100% to finish the year and advance to the next academic year. If either of the performances reaches to 0, you fail the year.
  • If you fail, you are presented with 3 options:
    • You can either restart college (restarting the entire game)
    • Or you can restart the academic year (restarting that particular level)
    • Or you can drop out (exiting the game)
  • If you finishing all four academic years, you win the game (congrats on graduating)
    • You will be given a diploma and introduced to “other games” (Career, Graduate schools, might be coming soon (no they aren’t, we are not doing those for real))

Arduino – Processing communication

  • Distance sensor is implemented as a remote control:
    • The Arduino program calculates how far the remote control is from a vertical surface
    • The distance is sent to Processing which will map the distance into the player’s horizontal coordinate
    • An icon representing the player’s position on the Processing screen is updated accordingly
  • Processing will check for collision with items. If there is a collision, a signal is sent to Arduino to play a sound on the buzzer
  • When the player is presented with a screen that has options (for example, the starting screen can have Instructions, Start game, the ending screen can have Restart college, Restart the year, Drop out), the player can use the potentiometer on the Arduino to traverse the options and press a button when the desired option is selected to proceed.
  • Processing receives the signal from the potentiometer and maps it to a range to decide which option is currently selected by the player and communicates this back to the player by highlighting the option.
  • Two tricolor LEDs on the Arduino are used to communicate the player’s current performances, one to represent academic performance and the other to represent well-being. If the player’s performance in either is fulfilled (reaches 100), the LED(s) turns green; if performance is adequate, the LED(s) turns blue/yellow (?); and if performance is low (approaching 0), the LED(s) turns red.

Exercises: Serial Comms

Exercise 1: I essentially modified the starter code such that the y position remained fixed in the middle of the screen.

Arduino:

int pot = A0;
 
void setup() {
  Serial.begin(9600);
  Serial.println("0");
  pinMode(pot, INPUT);
}
 
void loop() {
  while (Serial.available()) {
    if (Serial.read() == '\n') {
      int sensor = analogRead(A0);
      Serial.println(sensor);
    }
  }
}

Processing:

import processing.serial.*;
Serial myPort;
int xPos=0;
int yPos=height/2;
 
void setup(){
  size(960,720);
  printArray(Serial.list());
  String portname=Serial.list()[1];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}
 
void draw(){
  background(255);
  ellipse(xPos,yPos,30,30);
}
 
void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
    int val=int(s);
      xPos=(int)map(val,0,1023,0, width);
  }
  myPort.write("\n");
}

 

Exercise 2: I used the mouse speed from Processing to determine the brightness of the LED in Arduino.

Arduino code:

int ledPin = 5;
int bright;
 
void setup() {
  Serial.begin(9600);
  Serial.println("0");
  pinMode(ledPin, OUTPUT);
}
 
void loop() {
  while (Serial.available()) {
    bright = Serial.parseInt();
    if (Serial.read() == '\n') {
      analogWrite(ledPin, bright);
      Serial.print("\n");
    }
  }
}

Processing Code:

import processing.serial.*;
Serial myPort;
float mouseSpeed;
float smoothSpeed;
 
void setup(){
  size(960,720);
  printArray(Serial.list());
  String portname=Serial.list()[2];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}
 
void draw(){
  background(255);
  ellipse(mouseX, mouseY, 25, 25);
  mouseSpeed =  5 * dist(mouseX, mouseY, pmouseX, pmouseY);
  smoothSpeed = lerp(smoothSpeed, mouseSpeed, 0.1);
  println(smoothSpeed);
}
 
void serialEvent(Serial myPort){
  float val = map(smoothSpeed, 0, 400, 0, 255);
  myPort.write((int)val + "\n");
}

 

Exercise 3: The photoresistor affected the wind direction and each time the ball bounced on Processing, I wrote to the serial to communicate to Arudino that the LED should light up. I originally used a photoresistor, but it felt a bit clunky. I still find the response in the wind vector kind of slow but find the movement more intuitive than the potentiometer.

Arduino Code:

int phot = A0;
int led = 2;
int bounce = 0;
int pastVal;
int val;
void setup() {
  Serial.begin(9600);
  Serial.println("0,0");
  pinMode(led, OUTPUT);
  pinMode(phot, INPUT);
  val = analogRead(phot);
  pastVal = val;

}

void loop() {

  while (Serial.available()) {
    bounce = Serial.parseInt();
    if (bounce == 1) {
      digitalWrite(led, HIGH);
    } else {
      digitalWrite(led, LOW);
    }
    if (Serial.read() == '\n') {
      

      val = analogRead(phot);
      if (pastVal != val) {
        if (val >= 34) {
          Serial.println(1);
        } else {
          Serial.println(-1);
        }
        pastVal = val;
      }
      else {
        Serial.println(0);
      }
      }
     
    }
  }

 

Processing Code:

PVector velocity;
PVector gravity;
import processing.serial.*;
Serial myPort;

PVector position;
PVector acceleration;
PVector wind;
float drag = 0.99;
float mass = 50;
float hDampening;
int bounce = 0;

void setup() {
  size(640,360);
  noFill();
  position = new PVector(width/2, 0);
  velocity = new PVector(0,0);
  acceleration = new PVector(0,0);
  gravity = new PVector(0, 0.5*mass);
  wind = new PVector(0,0);
  hDampening=map(mass,15,80,.98,.96);
  
  String portname=Serial.list()[2];
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}

void draw() {
  background(255);
    velocity.x*=hDampening;
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  ellipse(position.x,position.y,mass,mass);
  if (position.y > height-mass/2) {
      velocity.y *= -0.9;  // A little dampening when hitting the bottom
      position.y = height-mass/2;
      bounce = 0;
    }
}
  
void applyForce(PVector force){
  // Newton's 2nd law: F = M * A
  // or A = F / M
  PVector f = PVector.div(force, mass);
  acceleration.add(f);
}

void keyPressed(){

  if (key==' '){
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
}

void serialEvent(Serial myPort){
  
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  
  if (s!=null) {
    int windVal = int(s);
    println(windVal);
    if (wind.x >= -1 || wind.x <= 1) {
      wind.x = windVal;
    }
  }
  
  if (round(velocity.y) < 0) {
    bounce = 1;
  } else {
    bounce = 0;
  }
  myPort.write(bounce + "\n");
}

 

 

 

 

 

Final Project Idea

For my midterm project i have several ideas, which i can implement using atduino and processing .

The first idea is a “therapy app” . It will include  different options and modes for different aims. Like relax or otherwise focusing.

The second idea is some sort  of the game travelling story, where you can make some exercises( small interactive games) to continue and reach the end of the story.  The theme i’m gonna choose is ecology to pay audience attention to a problems are happening now.

[Serial Communication Excercise] Cole and Minh

Exercise 1:

Excercise 2

Exercise 3:

const int ledPin = 11;
int brightness = 0;
const int sensorPin = A0;
 
void setup() {
  Serial.begin(9600);
  Serial.println("0,0");
  pinMode(ledPin, OUTPUT);
}
 
void loop() {
  while (Serial.available()) {
    int onOff = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(ledPin, onOff);
      int sensor = analogRead(sensorPin);
      delay(1);
      Serial.println(sensor);
    }
  }
}


//PROCESSING CODE
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  ellipse(position.x,position.y,mass,mass);
  fill(255,255,0);
  if (position.y > height-mass/2) {
      velocity.y *= -0.9;  // A little dampening when hitting the bottom
      position.y = height-mass/2;
      onOff = true;
  }
  else{
    onOff = false;
  }
}
 
void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  int val = parseInt(s);
  if (s!=null){
      wind.x=map(val,0,1023,-2, 2);  //2 instead of 1 to make it stronger
  }
  myPort.write(int(onOff)+"\n");
}
  
void applyForce(PVector force){
  // Newton's 2nd law: F = M * A
  // or A = F / M
  PVector f = PVector.div(force, mass);
  acceleration.add(f);
}

void keyPressed(){
  if (keyCode==LEFT){
    wind.x=-1;
  }
  if (keyCode==RIGHT){
    wind.x=1;
  }
  if (key==' '){
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
}

Video for exercise 3:

 

THREE ARDUINO EXERCISES

Exercise 1: make something that uses only one sensoron arduino and makes the ellipse in processing move on the horizontal axis, in the middle of the screen, and nothing on arduino is controlled by processing.

PROCESSING_EXERCISE 1

import processing.serial.*;// serial object library
Serial myPort; //local serial object from serial library
int xPos=0;
int yPos=0;
 
void setup(){
  size(960,720);
  printArray(Serial.list());
  String portname=Serial.list()[2]; //link processing to serial port
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}
 
void draw(){
  background(255);
  ellipse(xPos,height/2,30,30);
}
 
void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n'); //strips data of serial port
  s=trim(s);
  if (s!=null){
    
    println(s);
    int value=int(s);
    
    // locates position of ellipse using potentiometer
    xPos=(int)map(value,0,1023,0, width);
  
  }
  myPort.write("\n");
}

ARDUINO_EXERCISE 1

void setup() {
  //initialize the serial port and data upload
  Serial.begin(9600);
  Serial.println("0");
}
 
void loop() {
  //capture data in arduino 
  int sensor= analogRead(A0);
  //put data in the serial port
  while (Serial.available()) {
    if (Serial.read() == '\n') {
      delay(1);
      //prints the value
      Serial.println(sensor);
    }
  }
}

Exercise 2: make something that controls the LED brightness from processing.

PROCESSING_EXERCISE 2

import processing.serial.*;
Serial myPort;
int xPos=0;
int Sensor=0;
boolean Red=false;
boolean Green=false;
void setup(){
size(960,720);
printArray(Serial.list());
String portname=Serial.list()[2];
println(portname);
myPort = new Serial(this,portname,9600);
myPort.clear();
myPort.bufferUntil('\n');
}
void draw(){
background(255);
ellipse(mouseX,mouseY,30,30);
if ((mouseX >= 400) && (mouseY >= 600)) {
Red =true;
} else Red = false;
if ((mouseX <= 400) && (mouseY <= 600)){
Green =true;
}
else Green = false;

}
void serialEvent(Serial myPort){
String s=myPort.readStringUntil('\n');
s=trim(s);
if (s!=null){
println(s);
int values[]=int(split(s,','));
if (values.length==2){
xPos=(int)map(values[0],0,1023,0, width);

}
}
myPort.write(int(Red)+","+int(Green)+"\n");
print("0,0");
}

ARDUINO_EXERCISE 2

int left = 0;
int right = 0;

void setup() {
Serial.begin(9600);
Serial.println("0,0");
pinMode(2, OUTPUT);
pinMode(5, OUTPUT);
}

void loop() {
while (Serial.available()) {
right = Serial.parseInt();
//left = Serial.parseInt();
if (Serial.read() == '\n') {
digitalWrite(2, right);
//digitalWrite(5, left);
int sensor = analogRead(A0);
delay(1);
//int LDRPIN = analogRead(A1);
//delay(1);
Serial.print(sensor);
//Serial.print(',');
//Serial.println(LDRPIN);
}
}
}

Exercise 3: take the gravity wind example and make it so every time the ball bounces one led lights up and then turns off, and you can control the wind from one analog sensor.

PROCESSING_EXERCISE 3

import processing.serial.*;
Serial myPort;
int xPos=0;

int Sensor=0;
boolean Red=false;
boolean Green=false;
PVector velocity;
PVector gravity;
PVector position;
PVector acceleration;
PVector wind;
float drag = 0.99;
float mass = 50;
float hDampening;
void setup(){
size(640,360);
printArray(Serial.list());
String portname=Serial.list()[1];
println(portname);
myPort = new Serial(this,portname,9600);
myPort.clear();
myPort.bufferUntil('\n');
noFill();
position = new PVector(width/2, 0);
velocity = new PVector(0,0);
acceleration = new PVector(0,0);
gravity = new PVector(0, 0.5*mass);
wind = new PVector(0,0);
hDampening=map(mass,15,80,.98,.96);
}
void draw(){
background(255);
if (!keyPressed){
wind.x=0;
velocity.x*=hDampening;
}
applyForce(wind);
applyForce(gravity);
velocity.add(acceleration);
velocity.mult(drag);
position.add(velocity);
acceleration.mult(0);
ellipse(position.x,position.y,mass,mass);
if (position.y > height-mass/2) {
velocity.y *= -0.9; // A little dampening when hitting the bottom
position.y = height-mass/2;
Red = true; 
}
else { Red = false;
}
}
void serialEvent(Serial myPort){
String s=myPort.readStringUntil('\n');
s=trim(s);
if (s!=null){
println(s);
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);
}
}
myPort.write(int(Red)+","+int(Green)+"\n");
print("0,0");
}
void applyForce(PVector force){
// Newton's 2nd law: F = M * A
// or A = F / M
PVector f = PVector.div(force, mass);
acceleration.add(f);
}

void keyPressed(){
if (keyCode==LEFT){
wind.x=-1;
}
if (keyCode==RIGHT){
wind.x=1;
}
if (key==' '){
mass=random(15,80);
position.y=-mass;
velocity.mult(0);
}
}

ARDUINO_EXERCISE 3

int left = 0;
int right = 0;

void setup() {
Serial.begin(9600);
Serial.println("0,0");
pinMode(2, OUTPUT);
// pinMode(5, OUTPUT);
}

void loop() {
while (Serial.available()) {
right = Serial.parseInt();
left = Serial.parseInt();
if (Serial.read() == '\n') {
digitalWrite(2, right);
// digitalWrite(5, left);
int sensor = analogRead(A0);
//delay(1);
//int LDRPIN = analogRead(A1);
delay(1);
 Serial.print(sensor);
//Serial.print(',');
//Serial.println(LDRPIN);
}
}
}

LED Assignment – Hamad and Varya

Objective:

Arduino and Processing have numerous capabilities allowing them to connect to one another. Thus, this assignment presents these factors with three tasks my partner, Hamad, and I were instructed to follow.

Plan:

Go over what we touched upon in class and reference from numerous videos around the internet to explore the multiple ways possible to get to the goal desired.

Code:

Task 1:

ARDUINO & PROCESSING:

Task 2:

ARDUINO:

//INITIALIZE VARIABLE
float var;

//ARDUINO AND PROCESSING COMMUNICATION SETUP
void setup()
{
  Serial.begin(9600);
  //GET ONLY 1 INPUT - BRIGHTNESS
  Serial.println("0");
  pinMode(2, OUTPUT);
}

//MAIN FUNCTION
void loop()
{
  while (Serial.available())
  {
    //GET PROCESSING VARIABLE
    var = Serial.parseInt();
    if (Serial.read() == '\n') 
    {
      //GIVE LED BRIGHTNESS
      analogWrite(2, var); 
      Serial.println(var);
    }
  }
}

PROCESSING:

//LINK TO ARDUINO
import processing.serial.*;
Serial myPort;

//INITIALIZE VARIABLES
int xPos = 0;
float var;


void setup() 
{
  size(960, 720);
  printArray(Serial.list());
  String portname=Serial.list()[0];
  println(portname);
  myPort = new Serial(this, portname, 9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}

void draw() 
{
  background(255);
  ellipse(xPos, height/2, 30, 30);
  //GET X POSITION
  float var1 = mouseX; 
  //MAP WIDTH TO BRIGHTNESS
  var = map(var1, 0, width, 0, 255);
}

void serialEvent(Serial myPort) 
{ 
  String s=myPort.readStringUntil('\n');
  s = trim(s);
  if (s != null) 
  {
    println(s);
    int value = int(s);
    if (value >= 0) {
      xPos = (int)map(value, 0, 1023, 0, width);
    }
  }
  //SEND BACK MAPPED X VALUE TO ARDUINO
  myPort.write(var+ "\n");
}

 

Task 3:

ARDUINO:

//INITIALIZE VARIABLES
int left = 0;
int right = 0;
int var = 0;

//VARIBALES & LED SETUP
void setup()
{
  Serial.begin(9600);
  Serial.println("0,0");
  pinMode(2, OUTPUT);
}

void loop()
{
  while (Serial.available())
  {
    //STORES LED VALUE FROM PROCESSING
    var = Serial.parseInt();
    Serial.println(var);

    if (Serial.read() == '\n')
    {
      //TURN LED ON IF BALL TOUCHES GROUND
      if (var == 1)
      {
        digitalWrite(2, HIGH);
      }
    }

    //GET VALUES FROM POTENTIOMETER
    int sensor = analogRead(A0);
    delay(1);

    Serial.println(sensor);
  }
}

PROCESSING:

//LINK PROCESSING TO ARDUINO
import processing.serial.*;
Serial myPort;

//INITIALIZE VARIABLES
PVector velocity;
PVector gravity;
PVector position;
PVector acceleration;
PVector wind;
float drag = 0.99;
float mass = 50;
float hDampening;
int potValue; //variable from the potentiometer
int led = 0; //variable to change to switch the led off 

//REGULATIONS
void setup() 
{
  size(640, 360);
  noFill();
  position = new PVector(width/2, 0);
  velocity = new PVector(0, 0);
  acceleration = new PVector(0, 0);
  gravity = new PVector(0, 0.5*mass);
  wind = new PVector(0, 0);
  hDampening=map(mass, 15, 80, .98, .96);
}

//ARDUINO INTERACTION
void draw() 
{
  background(255);
  if (!keyPressed) 
  {
    //MOVE CIRCLE BASED ON POTENTIOMETER INPUT
    wind.x = potValue;
    velocity.x*=hDampening;
  }

  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  ellipse(position.x, position.y, mass, mass);
  if (position.y > height-mass/2) 
  {
    velocity.y *= -0.9;  
    position.y = height-mass/2;
  }
}

void applyForce(PVector force) 
{
  // Newton's 2nd law: F = M * A
  // or A = F / M
  PVector f = PVector.div(force, mass);
  acceleration.add(f);
}

void keyPressed() 
{
  if (keyCode==LEFT) 
  {
    wind.x=-1;
  }
  if (keyCode==RIGHT) 
  {
    wind.x=1;
  }
  if (key==' ') 
  {
    mass=random(15, 80);
    position.y=-mass;
    velocity.mult(0);
  }
}

void serialEvent(Serial myPort) 
{
  String s = myPort.readStringUntil('\n');
  s=trim(s);
  if (s != null) {
    int value = int(s);
    potValue = (int)map(value, 0, 1023, 0, width*.01);
  }

  //TURN LED ON IF BALL TOUCHES GROUND
  if (round(velocity.y) < 0) 
  {
    led = 1;
    myPort.write(int(led)+ "\n");
  }
}

 

VIDEO: (click)