problem with commnunicating arduino with processing (both sending and receiving)

hello everyone,

I'm now working on how to communicate arduino with processing in both way. means the processing can read value from arduino to trigger certain animation, and the arduino can trigger some events ( like led on) when the animation runs in a certain point.

I wrote two quick sketches in arduino and processing. it is a snake goes from left to the right side of the screen. when it hits the right side, it will stop, and the led of arduino will be on for a certain period (3 seconds). after that, the snake goes from left to right again, and the led should be off for the next round.

the problem of my sketch is, the led will light up once, but never turns off again. i tried everything I could yet it still wont work.

does anyone have the similar problem or can anyone help me out ?

i'm really appreciated!

here is the code in arduino
int signal2 = '1';
int signal3 = '0';
void setup()
{
** Serial.begin(9600);**
** pinMode(13, OUTPUT);**
** Serial.write(signal3);**
}
void loop() {
** byte check;**
** if (Serial.available()>0) {**
** check = Serial.read();**
** if(check == '0'){**
** digitalWrite(13, HIGH);**
** delay(3000); // wait for a second**
** Serial.write(signal2);**
** }**
** else {**
** digitalWrite(13, LOW);**
** Serial.write(signal3);**
** }**
** }**
}

======================

here is the code in processing:

import processing.opengl.*;
import processing.serial.*;
Serial port;
Mover[] mover;
int nummover = 1;
void setup() {
** frameRate(30);**
** size(1000,1000,OPENGL);**
** smooth();**
** background(0);**
** port = new Serial(this, "COM3", 9600);**
** mover = new Mover[nummover];**
** for(int i=0; i<nummover; i++) {**
__ mover*=new Mover();__
__
}__
__
}__
void draw() {
__
noStroke();__
__
background(255);__
__
int signal = port.read();__
__
if(signal == '1') {__
__
for (int i=0; i<nummover; i++) {__
_ mover
.putAhold = false;
}
}
for (int i=0; i<nummover; i++) {
mover
.update();
mover.checkedge();
mover.display();
}
int sta;
if(mover[0].putAhold == true) {
sta = '0';
}
else {
sta = '3';
}
port.write(sta);
println(sta);
}
class Mover {
PVector[] location;
PVector velocity;
PVector acc;
float theta=random(360);
float ra=6;
float co=20;
int tail = 250;
boolean putAhold = false;
Mover () {
location = new PVector[tail];
for (int i=0; i<tail; i++) {
location = new PVector(0,height/2);
}
velocity = new PVector(0,0);
}
void update() {
acc = new PVector(ra,cos(radians(theta))ra);
acc.normalize();

* velocity.add(acc);
if(putAhold == true) {
velocity.limit(0);
}
if(putAhold == false) {
velocity.limit(6);
}
for(int i=tail-2; i>=0; i--) {
location[i+1].x = location.x;
location[i+1].y = location.y;
location.add(velocity);
}
theta += 5;
}
void checkedge() {
for(int i=tail-2; i>=0; i--) {
if (location.x>width) {
location.x=0;
putAhold = true;
}
}
}
void display() {
for(int i=tail-2; i>=0; i--) {
strokeWeight(5);
stroke(0,(100-i1));
if(location[i+1].x - location*.x < 2) {
line(location.x, location.y, location[i+1].x, location[i+1].y);
}
}
}
}[/b]*_

int signal2 = '1';
int signal3 = '0';

Names like zero and one would make more sense.

for(int i=0; i<nummover; i++) {
mover=new Mover();
}
This is why the code buttons exists. Either the forum software or you screwed up this code. I'll assume that it was you posting the code incorrectly rather than you screwing up the code.

But, why do you have a one element array?

Serial data transfer is asynchronous. That means that you can never tell when it will happen. Yet, in the processing sketch, you assume that there will be data to read on every pass through draw().

You need to implement the serialEvent method, to handle serial data coming in. You'll need to figure out a way (global variables, typically) to make draw() and serialEvent() share data.

thank you paul!
the mover = new Mover was a mistake when i paste to the forum. i have .
i just set one becoz it's more clean for the first test. i actually will have more of this object.
I just tried with serialEvent as you suggested. but the problem is still there. here is my modified code in processing. I'll skip the mover class
import processing.opengl.*;
import processing.serial.*;
Serial myPort;
String signal;
Mover[] mover;
int nummover = 7;
int flag;
void setup() {

  • frameRate(30);*
  • size(1000,1000,OPENGL);*
  • smooth();*
  • background(0);*
  • println(Serial.list());*
  • myPort = new Serial(this, Serial.list()[0], 9600);*
  • mover = new Mover[nummover];*
  • myPort.bufferUntil('\n');*
  • for(int i=0; i<nummover; i++) {*
    _ mover*=new Mover();_
    _
    }_
    _
    }_
    void draw() {
    _
    noStroke();_
    _
    background(255);_
    _
    if(flag == '1') {_
    _
    for (int i=0; i<nummover; i++) {_
    _ mover.putAhold = false;
    }
    }
    for (int i=0; i<nummover; i++) {
    mover.update();
    mover.checkedge();
    mover.display();
    }
    int sta;
    if(mover[0].putAhold == true) {
    sta = '0';
    }
    else {
    sta = '3';
    }
    myPort.write(sta);
    println(sta);
    }
    void serialEvent(Serial myPort) {
    signal = myPort.readStringUntil('\n');
    flag = int(signal);
    }*_

the mover = new Mover was a mistake when i paste to the forum

So you repeated it?

Modify your posts. Select the code, and press the button with the # icon on it.

If you didn't change your Arduino code, your serialEvent() method is never called. It won't be called until the Arduino sends a carriage return, which it currently does not.

hi paul. I looked through the communication example in arduino. i did modified the code in arduino, yet it still stuck in the middle. It would be really helpful if u could tell me what kind of problem it is. i assume it might be the logic in processing code.

arduino

int signal1 = '1';
int signal0 = '0';
void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {
  byte check;
  if (Serial.available()>0) {
    check = Serial.read();
    if(check == '0') {
      digitalWrite(13, HIGH);
      delay(3000); 
      Serial.print(signal1);
    } else { 
    digitalWrite(13, LOW);
    Serial.print(signal0);
    }
  }
}

processing

import processing.opengl.*;
import processing.serial.*;
Serial myPort;

int signal;
Mover[] mover;
int nummover = 7;

void setup() {
  frameRate(30);
  size(1000,1000,OPENGL);
  smooth();
  background(0); 
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600);
  mover = new Mover[nummover];
  myPort.bufferUntil('\n');
  for(int i=0; i<nummover; i++) {
    mover[i]=new Mover();
  }
}

void draw() {
  noStroke();
  background(255);
 
  for (int i=0; i<nummover; i++) {
    mover[i].update();
    mover[i].checkedge();
    mover[i].display();
  }

  int sta;
  if(mover[0].putAhold == true) {
    sta = '0';
  } 
  else {
    sta = '3';
  }  
  myPort.write(sta);
  println(sta);
}

void serialEvent(Serial myPort) {
 signal = myPort.read();
   if(signal == '1') {
    //myPort.clear(); 
    for (int i=0; i<nummover; i++) {
      mover[i].putAhold = false;
    }
  }
}

thank you!

i did modified the code in arduino, yet it still stuck in the middle.

I have no idea what "it still stuck in the middle" means. I have no idea what "it" is.

However, the Processing code is going to buffer serial data until it receives a carriage return, because you told it to:

  myPort.bufferUntil('\n');

So, it might be useful in the Arduino code to actually send a carriage return, now and then. These are all of your serial statements:

  Serial.begin(9600);
  if (Serial.available()>0) {
    check = Serial.read();
      Serial.print(signal1);
    Serial.print(signal0);

None of these sends a carriage return.

Change the Serial.print() calls to Serial.println() calls to send the data followed by a carriage return/line feed.

hello paul, thanks for your replying again. however it is still not working. I change the Serial.println to Serial. write in arduino, becaus it keeps sending weird numbers.

I think the problem here is the arduino always read '1' from processing. I test them separately they work fine. the processing sending the correct number, and if i type in serial monitor in arduino, it response well too.

here is the code that I just modified

void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {
  int check;
  if (Serial.available()>0) {
    check = Serial.read();
    if(check == '0') {
      digitalWrite(13, HIGH);
      delay(3000); 
      Serial.write('1');
    } else { 
    digitalWrite(13, LOW);
    Serial.write('0');
    }
  }
}
import processing.opengl.*;
import processing.serial.*;
Serial myPort;

int signal;
Mover[] mover;
int nummover = 7;

void setup() {
  frameRate(30);
  size(1000,1000,OPENGL);
  smooth();
  background(0); 
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600);
  mover = new Mover[nummover];
  for(int i=0; i<nummover; i++) {
    mover[i]=new Mover();
  }
}

void draw() {
  noStroke();
  background(255);
  
  for (int i=0; i<nummover; i++) {
    mover[i].update();
    mover[i].checkedge();
    mover[i].display();
  }

  int sta;
  if(mover[0].putAhold == true) {
    sta = '0';
  } 
  else {
    sta = '3';
  }  
  myPort.write(sta);
  //println(sta);
}

void serialEvent(Serial myPort) {
 signal = myPort.read();  
 println(signal);
 if(signal == '1') {
    for (int i=0; i<nummover; i++) {
      mover[i].putAhold = false;
    }
  }  
}

I change the Serial.println to Serial. write in arduino, becaus it keeps sending weird numbers.

What does this mean?

With the changes you've made now, the serialEvent method never gets called. So, you will never read anything from the Arduino.

if u run the code, u will see the println(signal) is printing the values that received from arduino

That would require that I do a lot of work that I shouldn't need to do. You have the hardware setup with the sketches uploaded.

Just show me the latest code on the Arduino, the latest Processing sketch, and the output from the println() commands in Processing.

What is possibly causing an issue is that the Arduino is sending '1' as an int as a string, which means that it is sending the string "49". The string "49" is then being converted to an int, as 49, which, of course doesn't look like 1.

On the Arduino, change

int signal1 = '1';
int signal0 = '0';

to

int signal1 = 1;
int signal0 = 0;

hello Paul,

I dont think the problem is '1' or 1. I changed the value like u said, however it is still not working.

the processing is printing 0 when it hits the boundary and 3 when it is not. the problem is the arduino just cannot receive the 3 sent from processing....

the problem is the arduino just cannot receive the 3 sent from processing....

Yes, it can. Post your latest code.

int signal1 = 1;
int signal0 = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {
  byte check;
  if (Serial.available()>0) {
    check = Serial.read();
    if(check == 1) {
      digitalWrite(13, HIGH);
      delay(3000); 
      Serial.write(signal1);
    } else { 
    digitalWrite(13, LOW);
    Serial.write(signal0);
    }
  }
}
import processing.opengl.*;
import processing.serial.*;
Serial myPort;

int signal;
Mover[] mover;
int nummover = 7;
  int sta;
  
void setup() {
  frameRate(30);
  size(1000,1000,OPENGL);
  smooth();
  background(0); 
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600);
  mover = new Mover[nummover];
  for(int i=0; i<nummover; i++) {
    mover[i]=new Mover();
  }
}

void draw() {
  noStroke();
  background(255);  
  for (int i=0; i<nummover; i++) {
    mover[i].update();
    mover[i].checkedge();
    mover[i].display();
  }

  if(mover[0].putAhold == true) {
    sta = 1;
  } 
  else {
    sta = 3;
  }  
  myPort.write(sta);
  println(sta);
}

void serialEvent(Serial myPort) {
 signal = myPort.read();  
// println(signal);
 if(signal == 1) {
    for (int i=0; i<nummover; i++) {
      mover[i].putAhold = false;
    }
  }  
}

class Mover {
  PVector[] location;
  PVector velocity;
  PVector acc;
  float theta=random(360);
  float ra=6;
  float co=20;
  int tail = 250;
  boolean putAhold = false;

  Mover () {
    location = new PVector[tail];
    for (int i=0; i<tail; i++) { 
      location[i] = new PVector(0,height/2);
    }
    velocity = new PVector(0,0);
  }

  void update() {

    acc = new PVector(ra,cos(radians(theta))*ra);
    acc.normalize();
    velocity.add(acc);
    if(putAhold == true) {
      velocity.limit(0);
    } 
    if(putAhold == false) {
      velocity.limit(6);
    }

    for(int i=tail-2; i>=0; i--) {
      location[i+1].x = location[i].x;
      location[i+1].y = location[i].y;
      location[i].add(velocity);
    }
    theta += 5;
  }

  void checkedge() {
    for(int i=tail-2; i>=0; i--) { 
      if (location[i].x>width) {
        location[i].x=0;
        putAhold = true;
      }
    }
  }

  void display() {
    for(int i=tail-2; i>=0; i--) { 
      strokeWeight(5);
      stroke(0,(100-i*1));
      if(location[i+1].x - location[i].x < 2) {
        line(location[i].x, location[i].y, location[i+1].x, location[i+1].y);
      }
    }
  }
}

You aren't, by any chance, using a Mega, are you?

I only have an arduino duemilanove

do u think that is the cause?

I copied your processing sketch to the Processing IDE.

I copied your Arduino code to to the Arduino IDE. I compiled and linked it for my Mega, since that was handy. I uploaded it.

I started the Processing application, and watched the Processing application receive nothing from the Arduino.

I tried making a bunch of changes to both apps. No luck getting the Mega to do anything other than light the LED on pin 13 regardless of what was sent.

I unplugged the Mega, and plugged a Duemilanove in, and removed all of my changes to the Arduino code. I kept the change to the Processing code, that showed that the serialEvent method had been called, and everything worked.

The snakes stop moving when they hit the right wall, and start over.

Why this works for me on a Duemilanove, and not for you, and why is does not work for me on a Mega is a mystery.

hi paul

did the led on pin 13 turn off when the snake start over?

It did, but only very briefly, since, once the process repeated, the light was turned back on.

you mean, you use the code i posted and it works ?

What I want to achieve is, when the snake hit the edge, it will restart from left side, and hold for 3 seconds, during which the led will be on. and then the LED will be off until the snake hits the edge again

It works exactly like this?

hi paul,

the problem is that processing keep sending values to arduino, the queues is getting bigger and bigger.

i added this

int lastState = -1 // declare this before setup();

if(mover[0].putAhold == true) {
sta = 1;
}
else {
sta = 3;
}
if(lastState != sta) {
lastState = sta;
myPort.write(sta);
println(sta);
}

it works perfectly now
:slight_smile: