[SOLVED] Arduino button press should only spawn single object

I linked my code to my Arduino and replaced the “keyPressed” buttons for the “arduino.HIGH”
However, currently when I press a button, it registers as multiple presses at once. I realize this could be very well the cause of putting it in the draw, but I’ve no clue how to link it like I did with the keyPressed function.

Please let me know if you need the full code, since I only put the main page down below to have a brief overview of the main problem.

Here’s my code:

import processing.serial.*;
import cc.arduino.*;

JSONArray values;
ArrayList<Moon> manen = new ArrayList<Moon>();
ArrayList<Clouds> wolken = new ArrayList<Clouds>();

Arduino arduino;
int buttonOne;
int buttonTwo;
int buttonThree;
int buttonFour;

Planet planeet;
Vessel spaceSat;

boolean planetSpawn = false;
boolean satSpawn = false;

PImage temp; //screenshot
int saveP = 1;

PImage matte;

float x = 500;
float y = 110;
float diameter = 600;

void setup() {
  size(1600, 800);

  arduino = new Arduino(this, Arduino.list()[0], 57600);

  arduino.pinMode(7, Arduino.INPUT);
  arduino.pinMode(8, Arduino.INPUT);
  arduino.pinMode(6, Arduino.INPUT);
  arduino.pinMode(5, Arduino.INPUT);



  planeet = new Planet();
  spaceSat = new Vessel();

  matte = loadImage("matte.png");
}

void draw() {  
  background(0);

  buttonOne = arduino.digitalRead(8);
  buttonTwo = arduino.digitalRead(7);
  buttonThree = arduino.digitalRead(6);
  buttonFour = arduino.digitalRead(5);

  planeet.planetSpawnHere();

  for (Clouds b : wolken) {
    b.cloudPuff();
  }

  image(matte, 0, 0); //obscure layer for clouds

  for (Moon a : manen) {
    //a.orbitLines();
    a.whiteCirkel();
  }

  spaceSat.satSpawnHere();

  if (buttonOne == arduino.HIGH) {
    manen.add(new Moon(random(250, 380), random(20, 100), random(5, 45), random(0.002, 0.02), color(random(255), random(255), random(255))));
  }

  if (buttonTwo == arduino.HIGH) {
    wolken.add(new Clouds(random(30, 75), random(15, 30), random(150, 600), random(250, 350), random(0, 10)));
  }

  if (buttonThree == arduino.HIGH) {
    planeet.getRandom();
    planetSpawn = true;
  }

  if (buttonFour == arduino.HIGH) {
    spaceSat.getRandom();
    satSpawn = true;
  }
}

//void keyPressed() {
//if (buttonOne == arduino.HIGH) {
//  manen.add(new Moon(random(250, 380), random(20, 100), random(5, 45), random(0.002, 0.02), color(random(255), random(255), random(255))));
//}

//if (buttonTwo == arduino.HIGH) {
//  wolken.add(new Clouds(random(30, 75), random(15, 30), random(150, 600), random(250, 350), random(0, 10)));
//}

//if (buttonThree == arduino.HIGH) {
//  planeet.getRandom();
//  planetSpawn = true;
//}

//if (buttonFour == arduino.HIGH) {
//  spaceSat.getRandom();
//  satSpawn = true;
//}
//}

void keyTyped() {
  if (key == 'x') {
    PImage temp = get(415, 0, 770, 800); 
    temp.save("MyPlanet_" + saveP + ".png"); 
    saveP++;
  }
}

1 Like

use debounce button algorithm on your processing sketch to fix your problem, see https://www.arduino.cc/en/Tutorial/Debounce

the point is you need to evaluate if the button state has changed or not.

and:

Pushbuttons often generate spurious open/close transitions when pressed, due to mechanical and physical issues: these transitions may be read as multiple presses in a very short time fooling the program

1 Like

Thanks, I’ll check it out!

I found the following works:

import processing.serial.*;
import cc.arduino.*;

JSONArray values;
ArrayList<Moon> manen = new ArrayList<Moon>();
ArrayList<Clouds> wolken = new ArrayList<Clouds>();

Arduino arduino;
int buttonOne;
int buttonTwo;
int buttonThree;
int buttonFour;

boolean knopStop = false;

Planet planeet;
Vessel spaceSat;

boolean planetSpawn = false;
boolean satSpawn = false;

PImage temp; //screenshot
int saveP = 1;

PImage matte;

float x = 500;
float y = 110;
float diameter = 600;

void setup() {
  size(1600, 800);

  arduino = new Arduino(this, Arduino.list()[0], 57600);
  arduino.pinMode(7, Arduino.INPUT);
  arduino.pinMode(8, Arduino.INPUT);
  arduino.pinMode(6, Arduino.INPUT);
  arduino.pinMode(5, Arduino.INPUT);

  planeet = new Planet();
  spaceSat = new Vessel();

  matte = loadImage("matte.png");
}

void draw() {  
  background(0);

  buttonOne = arduino.digitalRead(8);
  buttonTwo = arduino.digitalRead(7);
  buttonThree = arduino.digitalRead(6);
  buttonFour = arduino.digitalRead(5);

  planeet.planetSpawnHere();

  for (Clouds b : wolken) {
    b.cloudPuff();
  }

  image(matte, 0, 0); //obscure layer for clouds

  for (Moon a : manen) {
    //a.orbitLines();
    a.whiteCirkel();
  }

  spaceSat.satSpawnHere();

  if (buttonOne == arduino.HIGH && knopStop == false) {
    knopStop = true;
    manen.add(new Moon(random(250, 380), random(20, 100), random(5, 45), random(0.002, 0.02), color(random(255), random(255), random(255))));
  } 
  if (buttonOne == arduino.LOW) {
    knopStop = false;
  }

  if (buttonTwo == arduino.HIGH) {
    wolken.add(new Clouds(random(30, 75), random(15, 30), random(150, 600), random(250, 350), random(0, 10)));
  }

  if (buttonThree == arduino.HIGH) {
    planeet.getRandom();
    planetSpawn = true;
  }

  if (buttonFour == arduino.HIGH) {
    spaceSat.getRandom();
    satSpawn = true;
  }
  
  println(knopStop);
}

void keyTyped() {
  if (key == 'x') {
    PImage temp = get(415, 0, 770, 800); 
    temp.save("MyPlanet_" + saveP + ".png"); 
    saveP++;
  }
}

However, this part only works when it’s assigned to buttonOne:

if (buttonOne == arduino.HIGH && knopStop == false) {
    knopStop = true;
    manen.add(new Moon(random(250, 380), random(20, 100), random(5, 45), random(0.002, 0.02), color(random(255), random(255), random(255))));
  } 
  if (buttonOne == arduino.LOW) {
    knopStop = false;
  }

The minute I assign it to the other buttons, it stops reading the knopStop boolean and spawns the objects simultaneously at a single button press.

2 Likes

I do not use Firmata so do not know what the protocols are.
Assuming Processing sends a request for input and Arduino returns data.
You are communicating at 57600 Baud and checking for a button press each frame (60 fps).

This was written to “simulate” a long button press and display this state of button.
It prints “Change” if there was a state change of button.
It prints “Pressed” for first button press but NOT the rest.

I often write quick little snippets of code to test code behavior and sharing.

boolean  b1 = false;
char  c1 = ' ';

int countNow;
int countLast;
int countInterval;

boolean state = false;
boolean stateChange = false;
boolean stateLast = false;

void setup() 
  {
  size(200, 200);
  countInterval = 2*60;
  }

void draw() 
  {  
  background(0);

  // 5 frames high and 60 frames low to simulate button presses incoming
  countNow = frameCount;
  if (countNow >= countInterval)
    {
    b1 = !b1;
    if (b1 == true)
      countInterval = countNow + 5;
    else
      countInterval = countNow + 60; 
    }
    
    state = b1;                                 // current state of b1
    
    if (state != stateLast) 
      stateChange = true; // if state change set to true
    
  // prints state of button 0 or 1
    int tmp1 = (b1) ? 1:0;
    if (stateChange) println();
    print(tmp1);    
    
    if (stateChange)
      { 
      print(" Change ");
      if (b1) print("Pressed");
      println();
      stateChange = false;
      }
     stateLast = state;  
   }
1 Like

I solved it! All I had to do was create a separate boolean for every button. So knopStop turned into knopStopOne, knopStopTwo etc.

2 Likes