Send 3 variable to Arduino?

Hi,

I’m trying to send 3 variable w1, w2 and phiV which are 3 parameter changing with the mouse tracking.
I was trying to place those variable in 3 arrays and add it in a string but it didn’t work.
I think there is one or several steps i have missed somewhere.
Can I send a float array or just an int array?
I put my program

import processing.serial.*;

Serial arduinoport; 

float w1, w2;
float w12twist = 10.0;
//int x=1;
int Um=100;
int Vm=100;
float phiU=0;
float phiV=HALF_PI/2;
float X1t, X2t,X3t,X4t,X5t;
float y=100.0;


String out; 
//char end = "z";

void setup() {
  size (500, 800);
//  frameRate(30);
//  colorMode(RGB, 255, 255, 255, 100);
  println("use mouse X for freq, mouse Y for VM phase and mouseWheel for w1/w2");
}

void draw() {
  
  int[] valueW1 = new int[1];
  int[] valueW2 = new int[1];
  int[] valuephiV = new int[1];

for (int i = 0; i < valueW1.length; i++) {
  
  valueW1[i] = int(w1*100000);
  valueW2[i] = int(w2*100000);
  valuephiV[i] = int (phiV*100000);
}
  
 
  printArray(valueW1);
  printArray(valueW2);
  printArray(valuephiV);
  
  //String out = nf(valueW1,4) + nf(valueW2,4) + nf(valuephiV,4);
  String out = nf(valueW1,3) + nf(valueW2,4) + nf(valuephiV,4);

   println(out); 
   
   arduinoport.write(out); 
   
   
    
    
  background(150,150,150);
  //For example
  for (int x=0;x<500;x++){
  w1 = mouseX/500.0/PI;
  w2 = 1.2*w1;
  //w2 = 12.0/w12twist*w1;
  
  //INTERPRETATION:
  //Si w12twist= 1 => 12 amplitude max pour une periode "quand le motif se repète" et X1t dephasés de 1/2 de periode de X2t
  //Si w12twist= 0.7 =>  bcp amplitude max avant que la periode repete et toujours meme dephasage
  //Si w12twist= 9.69 =>  bcp amplitude max avant que la periode repete et toujours meme dephasage
  
  
  phiV=PI*mouseY/500.0;
  //phiV=phiV+PI/4000; //vitesse lente et constante de "propagation?"
  //phiV=PI*mouseY/500.0;
  // decale X1t et X2t de la meme periode
  // !!! changer les constantes phiv et/ou phiU n'a pas d'incidence sur "le decalage" X1t et X2t
  float y=0.01;
  
  X1t= Um/2*cos(w1*x+phiU) - Vm/2*cos(w2*x+phiV);
  X2t= Um/2*cos(w1*x+phiU) + Vm/2*cos(w2*x+phiV);
  X3t= Um *exp (-y*x/2)* cos(w1*x+phiV);
  X4t= 50*cos(w1*x+phiV);
  //!!! nonce n'es pas la somme X5t= Um *exp (-y*x/2)* cos(w1*x+phiV)+ 50*cos(w1*x+phiV);
  //X5t= Um *exp (-y*x/2)* cos(*w1*x)+ Um;
  X5t = Um*sin(x*0.1)*sin(w1*x+phiV);
  //Draw something...

  noStroke();
  fill(0,w1 ,50);
  ellipse (x,X1t+150, 5, 5); 
  fill(0,50, w1);
  ellipse (x,X2t+350, 5, 5); 
  fill(w1,50, 0);
  ellipse (x,X3t+550, 5, 5); 
  ellipse (x,X4t+650,5,5);
  ellipse (x,X5t+750,5,5);
  //println(W1, w1, w2, w12twist, phiV);
  }
}

void mouseWheel(MouseEvent event) {
  w12twist += event.getCount()/10.0;  
}

After I will have to read it in Arduino, and I don’t know the way to do it, but I 'll see step by step.

Thanks

@bking
one way to do it:

import processing.serial.*;

Serial arduinoport; 

float w1, w2;
float w12twist = 10.0;
//int x=1;
int Um=100;
int Vm=100;
float phiU=0;
float phiV=HALF_PI/2;
float X1t, X2t, X3t, X4t, X5t;
float y=100.0;
int[] values;

String out; 
//char end = "z";

void setup() {
  size (500, 800);
  //  frameRate(30);
  //  colorMode(RGB, 255, 255, 255, 100);
  values = new int[3];

  arduinoport = new Serial(this, "COM0", 9600);    //replace 0 with the port the arduino is connected to (see arduino IDE)
  /*
  if on linux or macos, it's better to list all ports using: "String[] ports = arduinoport.list();"
   then look for the index of the port you want to connect to, and instead of "COMX" in the new Serial above,
   set ports[index]. 9600 is the baudrate, make sure this is the same in the arduino Serial monitor
   example:
   String[] ports = Serial.list();
   printArray(ports);
   arduinoport = new Serial(this,ports[0],9600);
   */
  println("use mouse X for freq, mouse Y for VM phase and mouseWheel for w1/w2");
}

void draw() {

  //int[] valueW1 = new int[1];
  //int[] valueW2 = new int[1];
  //int[] valuephiV = new int[1];
  values[0] = int(w1*100000);
  values[1] = int(w2*100000);
  values[2] = int (phiV*100000);
  int valueW1 = int(w1*100000);
  int valueW2 = int(w2*100000);
  int valuephiV = int(phiV*100000);
  //both possible

  //String out = nf(valueW1,4) + nf(valueW2,4) + nf(valuephiV,4);
  String out = nf(values[0], 3)+"*"+nf(values[1], 4) +"*"+ nf(values[2], 4)+"*";
  String out1 = nf(valueW1, 3) + "*" + nf(valueW2, 4) + "*" + nf(valuephiV, 4) + "*";

  //println(out); 
  //println(out1);

  arduinoport.write(out); 
  //or: arduinoport.write(out1);


  background(150, 150, 150);
  //For example
  for (int x=0; x<500; x++) {
    w1 = mouseX/500.0/PI;
    w2 = 1.2*w1;
    //w2 = 12.0/w12twist*w1;

    //INTERPRETATION:
    //Si w12twist= 1 => 12 amplitude max pour une periode "quand le motif se repète" et X1t dephasés de 1/2 de periode de X2t
    //Si w12twist= 0.7 =>  bcp amplitude max avant que la periode repete et toujours meme dephasage
    //Si w12twist= 9.69 =>  bcp amplitude max avant que la periode repete et toujours meme dephasage


    phiV=PI*mouseY/500.0;
    //phiV=phiV+PI/4000; //vitesse lente et constante de "propagation?"
    //phiV=PI*mouseY/500.0;
    // decale X1t et X2t de la meme periode
    // !!! changer les constantes phiv et/ou phiU n'a pas d'incidence sur "le decalage" X1t et X2t
    float y=0.01;

    X1t= Um/2*cos(w1*x+phiU) - Vm/2*cos(w2*x+phiV);
    X2t= Um/2*cos(w1*x+phiU) + Vm/2*cos(w2*x+phiV);
    X3t= Um *exp (-y*x/2)* cos(w1*x+phiV);
    X4t= 50*cos(w1*x+phiV);
    //!!! nonce n'es pas la somme X5t= Um *exp (-y*x/2)* cos(w1*x+phiV)+ 50*cos(w1*x+phiV);
    //X5t= Um *exp (-y*x/2)* cos(*w1*x)+ Um;
    X5t = Um*sin(x*0.1)*sin(w1*x+phiV);
    //Draw something...

    noStroke();
    fill(0, w1, 50);
    ellipse (x, X1t+150, 5, 5); 
    fill(0, 50, w1);
    ellipse (x, X2t+350, 5, 5); 
    fill(w1, 50, 0);
    ellipse (x, X3t+550, 5, 5); 
    ellipse (x, X4t+650, 5, 5);
    ellipse (x, X5t+750, 5, 5);
    //println(W1, w1, w2, w12twist, phiV);
  }
}

void mouseWheel(MouseEvent event) {
  w12twist += event.getCount()/10.0;
}

as you’re using 1D arrays,it’s not useful to use 3 separate arrays. either use 1 2D array or 3 separate variables.
also, in order to see when one value stops and the other begins (necessary for reading on the Arduino), split them with a different character, in this case i used " * " , but it can be anything as long as it isn’t a number.
then on the Arduino use Serial.readStringUntil(" * "); to read until this character to get the value in front of it.
use a for-loop to get all 3 values.

Hello M. Whahahahaha

Thanks you to have cleaning up my program. I can see my 3 values with:

String out = nf(values[0], 3)+"*"+nf(values[1], 4) +"*"+ nf(values[2], 4)+"*";

then you explain to me:
" on the Arduino use Serial.readStringUntil(" * “); to read until this character to get the value in front of it.
use a for-loop to get all 3 values.”

But, I’m a big noob so I tried to find a program to approach your solution but i guess I miss somethings :
the ARDUINO program below is in void loop

  // see if there's incoming serial data: (from processing)
  
    if(Serial.available()>0)      // while there is data
 {
  
   // First read the string until the '*' in your example
    // "1;130" this would read the "1" as a String
    
    String pulsation_str = Serial.readStringUntil('*');

    // split the string on the * and convert the resulting substrings
      // into an integer array:
      int [] omega = int (split(pulsation_str, "*"));
      // if the array has at least three elements, you know you got the whole
      // thing.  Put the numbers in the omega variables:
      if (omega.length >= 3) {
      
        w1 = omega[0];
        w2= omega[1]; 
        phiV= omega[2];

       }

       }

Morever, i have a little problem of exit status:
expected unqualified-id before ‘[’ token
due to this
int [] omega = int (split(pulsation_str, “*”));

Thanks again

Hi bking,

You can go see this thread, it should be quite similar to your problem: Multiple Values from processing to arduino through Serial Port

void receiveData() {
  if (Serial.available() > 0) {
    x = Serial.parseInt();
    y = Serial.parseInt();
    Serial.read();

Ok i will check it tomorrow but it seems to be too simple.

I hope to have the solution of Whahahahaha

Thanks you

Not sure why you say it is too simple… I must have missed something.

Hi,

Thanks for your help jb4x

Yours two programs work but we must add this in Arduino

boolean newData;

What I like in your program that it seems to receive to separate variables, but it’s completely different than the method of M. Whahahahaha.

(that why I said it seems to be too simple)

So for now, I will have to try send my 3 variables but it’s possible without the use of array?

Well yeah, it is definitly possible without any array.

The code I gave you can be easilly be scaled for 3 or more variables. I’m atually using something really similar to send the color of each LEDs in this porject: A universal ambilight. And it is way more than 3 variables :slight_smile:

@bking the code you provided seems to be for processing as well. Arduino declares arrays differently:

int omega[] = *whatever data*;

also Arduino doesn’t know the functions split() and array.length (like you use omega.length >= 3)
@jb4x 's code is actually better than what I had in mind, because Serial.parseInt() reads an integer value from the serial buffer until a non-integer is found, like * in this example.
of you then do:

w1 = Serial.parseInt();
w2 = Serial.parseInt();
phiV = Serial.parseInt();

it reads all values from the one string you sent.

this would go instead of your Serial.readStringUntil("*"); and the array omega[ ]
also doesn’t have to be inside a function like @jb4x has, just inside loop(){

actually if you want to learn more, take a look at this:
https://forum.arduino.cc/index.php?topic=288234.0
it also goes over splitting data at the bottom of the first post.
it actually says Serial.parseInt() and Serial.readStringUntil() are pretty bad ways to split Serial data.
instead look more into the strtok functions.

It is not always a bad way to split data.

The plus side of this is that it is super easy to implement. Then if you don’t need to do anything until you receive your data, the limitation explained in the link you gave is not a problem. It really depends on what you want to do.

Hi Whahahahaha and jb4x

I have tried the solution of jb4x with the Processing program,

But values are not stable at all, and the problem is that I can’t check it into the serial monitor of Arduino (is busy) when Processing is working.

I just want to send 3 values which changing with mouse x and mouse y and the third value is proportional at values[0]

I re-adapt my values values[0] values[1] and values[2] in order to have it between 0 and 255.

And an other problem: 3 values seems to be assigned even when I write only 2 values like that
arduinoport.write(values[1] + “,” + values[2] + “,”);

The Processing program

void draw() {
  
 //int[] valueW1 = new int[1];
 //int[] valueW2 = new int[1];
 //int[] valuephiV = new int[1];
  values[0] = int(w1*1000);
  values[1] = int(w2*1000);
  values[2] = int(phiV*100);

  //both possible


  //String out = nf(values[0],0)+"*"+nf(values[1], 2) +"*"+ nf(values[2], 2)+"*"; (simpler)
  //String out1 = nf(valueW1, 3) + "*" + nf(valueW2, 4) + "*" + nf(valuephiV, 4) + "*";

  //println(out); 
  //println(out1);
  
  //arduinoport.write(out); 
  //arduinoport.write(out1);
  
  //or

  //arduinoport.write(values[0] + "*" + values[1] + "*" + values[2] + "*");
  
    // SIMPLE WAY of JB4x
    
  // arduinoport.write(values[0] + ";" + values[1] + ";" + values[2] + ";"); first test
  arduinoport.write(values[1] + "," + values[2] + ","); //  why not the coma? other problem 3 values seems to be assigned
  println(values[0],values[1], values[2] );

and the Arduino program

void loop()  {

   // read the sensor value: (the potar)
  //  int sensorReading = analogRead(A0);

   //  send sensorReading to Serial (to receive it in Processing)
   //Serial.print(analogRead(sensorReading));   
  
  
   // _____________________________________________
   // see if there's incoming serial data: (from processing)
  
    if(Serial.available()>0)      // while there is data
 {
  
      w1 = Serial.parseInt();
      w2 = Serial.parseInt();
      phiV = Serial.parseInt();
      Serial.read();
 
  
     }

     Setpoint = w1;
     stateB= w2;
     stateD= phiV; 
   
 //  Serial.println (Setpoint); we can't see Setpoint when Processing works because the Serial is busy

After I will try to send value from Arduino to Processing with the same both programs. (but it seems it has worked).

Thanks

Hi,

Finally, I can receive my 3 variables in Arduino just by making exactly what jb4x said in his first post!!! (changing the speed of connection, use recevieData…)

see the Arduino Code below

    Setpoint = 0;
     stateB= 0;
     stateD= 0; 
  
}
 
void loop()  {

   // read the sensor value: (the potar)
  //  int sensorReading = analogRead(A0);

   //  send sensorReading to Serial (to receive it in Processing)
   //Serial.print(analogRead(sensorReading));   
  
  
   // _____________________________________________
   // see if there's incoming serial data: (from processing)
  receiveData();
   

     Setpoint = map( w1, 0,255, -100,100); //1er
     stateB= map( w2, 0,200, -100,100);
     stateD= map( phiV, 0,255, -100,100); // 3eme
   
 // Serial.print ("Setpoint :"); Serial.println (Setpoint); we can't see Setpoint when Processing works because the Serial is busy

void receiveData() {
  
  if (Serial.available() > 0) {
    w1= Serial.parseInt();
    w2 = Serial.parseInt();
    phiV =  Serial.parseInt();
    Serial.read();
  }
  }

in processing there is no effect if I do this

// arduinoport.write(values[0] + “;” + values[2] + “;” + values[1] + “;”);
arduinoport.write(values[1] + " " + values[2] + " " + values[0] + " ");

To finish I want to send one or several value from Arduino to Processing with the same both program.

I’ll come back if I have any problem.

Thanks Jb4x to be patient, your project A universal ambilight looks pretty good and useful to learn making nice project.

Thanks to M. Whahahahaha