Sending 0s and 1s to processing via arduino, Update of values is extremely slow

Hello there,

I’m trying to build a guitar hero-esque game using the arduino and processing, basically the arduino outputs viibration or lights to the buttons that have to be pressed, and if they’re pressed correctly, it sends a ‘1’ to the serial and if its wrong, it sends a ‘0’ .

After a lot of struggle I managed to get processing to read the string , convert it to a float and check for whether its 1 or 0, this controls whether the volume of the music is high or low, signifying success and failure . but when i run it i get a very long string of just 1’s for a very long time , and then the same for 0s.

In the arduino serial monitor, these values update quite accurately. how do i get the same accuracy with processing?

Arduino code:

 #include "eott.h"
  boolean Button1flag= LOW; // these are flags... I don't know why these are here
  boolean Button2flag= LOW;
  boolean Button3flag= LOW;
  
  int Buttonstate1 ; // these are the button states, read from the arduino
  int Buttonstate2 ;
  int Buttonstate3 ;


  int A=0;
  int B=0;
  int C=0;
  
  int i=0; // i will drive the array row change
  
  
  /* this is the array that would correspond to the song, a poor substitute for a MIDI file but simple. every row is a 25 ms block of the song.
  This is a test , ideally the array would be stored outside the code so I can call different 'songs'*/
   


  
  long Delay= 137.6121539054329; //this is the delay, and the duration for which each loop will run
  long t=0; // millis wil keep track of the time
  
void setup() {

// First define all the inputs and outputs
  pinMode(11,INPUT); // Pins 2,3,4 are the inputs where the buttons will be connected
  pinMode(12,INPUT);
  pinMode(13,INPUT);
  pinMode(2,OUTPUT); // Pins 11,12,13 are the outputs where the vibration motors will be connected (and mounted to the vibrators)
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(8,OUTPUT);
  Serial.begin(115200); // start the serial code at 9600 bpa
}

void loop() {
    if (i<=167)
 {
  i++;
 }
else {i=0;}//{while(1);}
 A= array[i][0];
 B= array[i][1];
 C= array[i][2];
   digitalWrite(2,A);
   digitalWrite(3,B);
   digitalWrite(4,C);
   digitalWrite(8,LOW);
  
  
  // put your main code here, to run repeatedly:
while (millis()<=t+Delay) // run the loop while the current value of millis is less than the sum of the previous time and the delay value
{
   Buttonstate1 = digitalRead(11); // these are the button states, read from the arduino
   Buttonstate2 = digitalRead(12);
   Buttonstate3 = digitalRead(13);
   
  if (Buttonstate1==A) //first condition: is button1 equal to the corresponding array value?
      {if (Buttonstate2==B) // second condition
          {if  (Buttonstate3==C) // basically if all three conditions are not met, the output is false
              {
                Serial.println("1"); // send a signal to processing to increase the volume of the song to signify success
                digitalWrite(8,HIGH);
                }
              }
    
  
  }
  else {
        Serial.println("0"); // this will tell processing to reduce the volume of the song, signifying failure.
        digitalWrite(8, LOW);
        }
  }
  t=millis();

/*
Serial.print(A);{0,0,0},

Serial.print("\t");
Serial.print(B);
Serial.print("\t");
Serial.print(C);
Serial.print("\t");
*/
}

Processing code:

/**
  * This sketch demonstrates how to play a file with Minim using an AudioPlayer. 

  * It's also a good example of how to draw the waveform of the audio. Full documentation 
  * for AudioPlayer can be found at http://code.compartmental.net/minim/audioplayer_class_audioplayer.html
  * <p>
  * For more information about Minim and additional features, 
  * visit http://code.compartmental.net/minim/
  */
import processing.serial.*;
import ddf.minim.*;

Serial myPort;
String val;
float a;

Minim minim;
AudioPlayer player;

void setup()
{
  
  myPort = new Serial(this, "COM3", 115200);
  
  size(512, 200, P3D);
   
  // we pass this to Minim so that it can load files from the data directory
  minim = new Minim(this);
  
  // loadFile will look in all the same places as loadImage does.
  // this means you can find files that are in the data folder and the 
  // sketch folder. you can also pass an absolute path, or a URL.
  player = minim.loadFile("Highway to Hell.wav");
}

void draw()
{
  if ( myPort.available() > 0) 
  {  // If data is available,
  val =  (myPort.readStringUntil('\n')); 
     if (val != null) {
       val =trim(val);
     a = float(val);
     println(a);
     }
     }
 if(a==1)
 {
  player.setGain(0); 
 }
 else if(a==0)
 {
   player.setGain(-30);
 }
  //println(val);
   if (mousePressed == true) 
  {                           //if we clicked in the window
   myPort.write('1');         //send a 1
   println("1");   
  } else 
  {                           //otherwise
  myPort.write('0');          //send a 0
  }   
  
  
  background(0);
  stroke(255);
  
  // draw the waveforms
  // the values returned by left.get() and right.get() will be between -1 and 1,
  // so we need to scale them up to see the waveform
  // note that if the file is MONO, left.get() and right.get() will return the same value
  for(int i = 0; i < player.bufferSize() - 1; i++)
  {
    float x1 = map( i, 0, player.bufferSize(), 0, width );
    float x2 = map( i+1, 0, player.bufferSize(), 0, width );
    line( x1, 50 + player.left.get(i)*50, x2, 50 + player.left.get(i+1)*50 );
    line( x1, 150 + player.right.get(i)*50, x2, 150 + player.right.get(i+1)*50 );
  }
  
  // draw a line to show where in the song playback is currently located
  float posx = map(player.position(), 0, player.length(), 0, width);
  stroke(0,200,0);
  line(posx, 0, posx, height);
  
  if ( player.isPlaying() )
  {
    text("Press any key to pause playback.", 10, 20 );
  }
  else
  {
    text("Press any key to start playback.", 10, 20 );
  }


if (keyPressed)
{
  {if(key == 'b')
  if ( player.isPlaying() )
  {
    player.pause();
    
  }
  
  // if the player is at the end of the file,
  // we have to rewind it before telling it to play again
  else if ( player.position() == player.length() )
  {
    player.rewind();
    player.play();
  }
  else
  {
    player.play();
  }
  }}}

I’m sorry about how ugly the processing code is, I’ve been trying a lot of different combinations of snippets of code to try and make it work

Thank you in advance for any help you can offer!

After a lot of struggle I managed to get processing to read the string , convert it to a float and check for whether its 1 or 0

Why would you need to convert a character to a float to see if it is a ‘0’ or a ‘1’?

  long Delay= 137.6121539054329; //this is the delay, and the duration for which each loop will run

A long is a kind of integer. Doesn’t seem likely that you’ll be able to store that value in an integer-type variable.

Serial IO is not supposed to be done in draw(). Unlike loop(), draw() is not called as fast as possible. It is called at a specific frame rate.

Your Arduino sketch needs to send ONE value when a switch BECOMES pressed. It should not send a steady stream of data when a switch IS pressed or is not pressed.

I tried checking while it was a string but it showed me an error saying string wasn't a valid data type for

if (a==1)

A long is a kind of integer. Doesn't seem likely that you'll be able to store that value in an integer-type variable.

I do not want to send the long value to processing, just 0s and 1s. the only thing is they should update in real time.

Serial IO is not supposed to be done in draw(). Unlike loop(), draw() is not called as fast as possible. It is called at a specific frame rate.

Then should I try moving that to a different loop? I've seen some void serialEvent() loops with serial functions in them.. is this what I would have to do?

Your Arduino sketch needs to send ONE value when a switch BECOMES pressed. It should not send a steady stream of data when a switch IS pressed or is not pressed.

I suppose I could do this by simply removing the Serial.println("0") from the else loop, but I do need arduino to send processing a value for every instance that the user is fulfilling all the three if conditions, so if they fail it registers immediately and lowers the volume of the music.

I tried checking while it was a string but it showed me an error saying string wasn't a valid data type for

Of course not. But, it would be valid to compare the string to "1" or "0".

I do not want to send the long value to processing

So? The long still can't hold a number with a fractional value.

Then should I try moving that to a different loop? I've seen some void serialEvent() loops with serial functions in them.. is this what I would have to do?

Yes, but that is not the real problem.

I suppose I could do this by simply removing the Serial.println("0") from the else loop, but I do need arduino to send processing a value for every instance that the user is fulfilling all the three if conditions, so if they fail it registers immediately and lowers the volume of the music.

No, you don't. You need to send a value when the third switch has become pressed.

Forget about Processing for now. Open the Serial Monitor application and see what your program is sending. Press the switches in the proper order and see what happens. Press them in the wrong order and see what happens.

Of course not. But, it would be valid to compare the string to "1" or "0".

Oh wow.. did not know I could do that, thanks!

So? The long still can't hold a number with a fractional value.

Crap, Didn't know that either.. is there a way I can use a fractional value in this code? maybe converting t=millis() to a float? can I then add/subtract and compare the values the same way that I am right now?

No, you don't. You need to send a value when the third switch has become pressed.

Forget about Processing for now. Open the Serial Monitor application and see what your program is sending. Press the switches in the proper order and see what happens. Press them in the wrong order and see what happens.

basically what I'm comparing the button values against is an array that had about 198 rows (its a test array) and 3 columns. I'm assigning these columns to A B and C and then comparing those values to the button states.

there are two possibilities, the buttons' values are the same as those in the particular row of the array, or they aren't.

I tested the serial monitor extensively and what happens is that when nothing is pressed, it continuously sends 1's , when any of the array values turns to 1, if that corresponding button is not pressed, it sends a 0. its fairly accurate even, I know this because I'm using a file that's basically playing the rhythm of eye of the tiger , and the 0s and 1s line up pretty accurately

Here's a photo of the setup, for reference

Also , thank you so much for taking the time to actually help me.

is there a way I can use a fractional value in this code?

Yes, using float or double as the type.

there are two possibilities, the buttons' values are the same as those in the particular row of the array, or they aren't.

I understand that AT SOME POINT IN TIME is makes sense to test the three button states. The question is when? On every pass through loop()? Or, only when the state of a switch changes to pressed?

I tested the serial monitor extensively and what happens is that when nothing is pressed, it continuously sends 1's

And the same stream of 1s is sent to Processing, which pops then off the stream at the rate of 30 a second (unless you've changed the frame rate). Since you are sending far more than 30 per second, of course Processing is going to fall behind.

I understand that AT SOME POINT IN TIME is makes sense to test the three button states. The question is when? On every pass through loop()? Or, only when the state of a switch changes to pressed?

well the array looks something like this:

{1,0,1},
{1,0,1},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{1,0,1},
{1,0,1},
{0,0,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,1,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},

so there are times when all three buttons are not pressed, and some are pressed and some aren't . I 'm having the code check through each loop because

a) It's the only way I know how
b) If the buttons were pressed correctly in the previous {{1,0,1}, say, and then they are not pressed again, if I'm not updating the read won't that just keep the value of the previous read all through the code?

I hope I'm understanding what you're saying correctly

And the same stream of 1s is sent to Processing, which pops then off the stream at the rate of 30 a second (unless you've changed the frame rate). Since you are sending far more than 30 per second, of course Processing is going to fall behind.

I wasn't aware that processing ran at only 30 loops a second... :\ I'll look into what frame rate is. do you think upping the frame rate would solve the issue?

On a side note, since the loop in arduino runs once every 137 ms , it can't send refreshed values (ofcourse its sending its values as fast as it can) more than 10 times a second