Having trouble dislaying images correctly on Processing.

So I've set up a simple program using an arduino, a photocell and Processing. Basically it detects if when there's no light and shows the information on a simple display. Processing uses the info from the serial monitor. If there is no light it shows one image (PLAN1). When it detects a certain level of light it shows another image (PLAN2). This is all it is going to do. I'm pretty new to this so had to look through the basics of processing for a while but I got it to work, just not properly. At the moment it shows PLAN2 ok. But when I cove the photocell it shows PLAN1 but it overlays it. This is because I had to use the tint() function to get it to work. I just want it to switch between images without having to use tint. I said I'd ask in a forum seeing as I couldn't find any info online. Any help at all would be greatly appreciated.

Here's the code for Processing:

import processing.serial.*;
Serial myPort;
String sensorReading="";

PImage img;
PImage img2;
//PImage bg;

void setup() {
size(1300, 1000);

String portName = Serial.list()[0];

img = loadImage("PLAN1.png");
img2 = loadImage("PLAN2.png");

// bg = loadImage("PLAN2.png");

myPort = new Serial(this, portName, 9600);
//myPort.bufferUntil('1');

}

void draw() {

//image(img, 0, 0);
//The serialEvent controls the display
}

void serialEvent (Serial myPort) {
sensorReading = myPort.readStringUntil('1');

if (sensorReading != null) {
noTint(); image(img, 0, 0);
}

else { tint(255,100); image(img2, 0, 0) ;

}

}

The image display should occur in the draw() function. The decision as to which image to display (in draw) should be based on a value that is set in the serialEvent callback.

I tried putting it in the draw() function but it wouldn't change back when I pulled my hand away from the photocell. It starts off by showing PLAN2, when I cover it it shows PLAN1 perfectly, but then when I uncover it it doesn't change back to PLAN2. Any idea what the problem could be? What value should I put in the serialEvent callback? Sorry if these questions are obvious but I'm just getting the hang of it.

What value should I put in the serialEvent callback?

I don't know what your code looks like now, so I can't tell you that. (Use the # icon when posting code.)

It starts off by showing PLAN2, when I cover it it shows PLAN1 perfectly, but then when I uncover it it doesn't change back to PLAN2.

Could be an Arduino problem, too. Can't say for sure without seeing the Arduino code.

Ok so here's the arduino code. I took it from a basic night light example:

/*
This example shows the output of an analogRead() of a Photocell.
 By M.Gonzalez
 www.codingcolor.com
 The example code is in the public domain
 */

int photocellPin = 0;// Photocell connected to analog pin 0
int photocellVal = 0; // define photocell variable
int ledPin = 9;// LED connected to digital pin 9
int ledState = 0;//state of the led 
int fadeDown = 30;//delay per fade
int fadeUp = 20;//delay per fade
int minLight = 200;//min light threshold
int maxLight = 300;//max light threshold


void setup() {
  //Serial.begin(9600);
  pinMode(photocellPin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}
void loop() {
  photocellVal = analogRead(photocellPin);

  if (photocellVal < minLight and ledState == 0){
    fadeLed(1);
    //Serial.println("fade up");
  }                      
  else if (photocellVal > maxLight and ledState == 1){
    fadeLed(0);
    // Serial.println("fade down");
  } 



}

void fadeLed(int num){
  if (num == 1){
    for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { 
      analogWrite(ledPin, fadeValue);             
      delay(fadeUp);                            
    } 
    ledState = 1;
    
    Serial.println("1");



  } 
  else{  
    for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { 
      analogWrite(ledPin, fadeValue);             
      delay(fadeDown);                            
    } 
    ledState = 0;
    
    Serial.println("2");
    

} 


}

The Processing code looks like this now.

import processing.serial.*;
Serial myPort;
String sensorReading="";

PImage img;
PImage img2;
//PImage bg;


void setup() {
  size(1300, 1000);
        
  String portName = Serial.list()[0];

  img = loadImage("PLAN1.png");
  img2 = loadImage("PLAN2.png");

 // bg = loadImage("PLAN2.png");
  
  myPort = new Serial(this, portName, 9600);
  //myPort.bufferUntil('1');
 

}

void draw() {
  
  if (sensorReading != null) {
     image(img, 0, 0);
  }
    
    
    
    else {   image(img2, 0, 0) ;
    
}
}  

void serialEvent (Serial myPort) {
  sensorReading = myPort.readStringUntil('1');
 
  
  }

As I said, it works to some extent now. It starts off by showing PLAN2, when I cover it it shows PLAN1 perfectly, but then when I uncover it it doesn't change back to PLAN2. The Processing code I posted in the first post probably looks better, even if it is tinted. I'd love to just get it working. I got to the stage I'm at now by tinkering with the code on each side. There's more than likely code I don't need but I don't mind as long as it's working. Any ideas? Thanks again for replying.

  sensorReading = myPort.readStringUntil('1');

Read the serial data until a 1 arrives. Store the data in a string variable. I don't know what you are thinking, here.

The Arduino sends a character, '1' or '2', followed by a carriage return and line feed. The Processing application should read the string until the carriage return arrives.

Thanks again, I'm new to coding but figuring it out. Ok so after a bit of work and thanks to your help I got a bit further. In Processing, I changed the this section of code

myPort = new Serial(this, portName, 9600);
  myPort.bufferUntil('\r');

and this

void serialEvent (Serial myPort) {
  sensorReading = myPort.readStringUntil('\n');
 
  
  }

and now it is one step closer to working.

It didn't work at all with myPort.readStringUntil('\r') so I changed it to myPort.readStringUntil('\n')

What happens now is it starts with PLAN2, then I cover the light and the image quickly fades to PLAN1. No tint, it looks clean. I uncover the light and it changes back to PLAN2. Perfect, all seems good. I then cover the light again and it wont change back to PLAN1. It stops to work. I also the led connected so I know the arduino is still reading the light. To get it to keep working again I have to quit the Processing app and restart.

I'm thinking there should be some type of loop or refresh command to restart the sensorReading.

I'm thinking there should be some type of loop or refresh command to restart the sensorReading.

You can use the print() function, to print to the bottom of the IDE window. Use that to print information when the serialEvent() callback gets called, to print what was read from the serial port, etc.

sensorReading should contain "1" or "2". Unless you changed the code in draw(), as soon as sensorRead is value in the callback, the image changes. There is no way to unvalue sensorReading, as your code is written.

I think that the draw() function should display an image based on the actual value in sensorReading, not the presence or absence of a value.

I think I understand what you mean. The sensorReading can't be null again. So I should change that line. So it should look something like this:

void draw() {
  
  if (sensorReading = "1") {
     image(img, 0, 0);
  }
    
    
    
     if (sensorReading = "2") {
     image(img, 0, 0);
  }
    
}
}

Would that be correct?

Would that be correct?

Yes.

Ok, sorry about all these questions now but I'm so close. changed them from if

(sensorReading != null) {
     image(img, 0, 0);
  }

to

if (sensorReading == "1") {
     image(img, 0, 0);
  }

like I said above and now it's not showing any images at all! I thought that would work. This is a bit of a disaster! It must have omething to do with how it's readin the serail monitor. The serial monitor just prints

1 
2 
1 
2 
1 
2

so maybe that's what the problem is. I'm really stumped on this one.

What did you mean by

You can use the print() function, to print to the bottom of the IDE window. Use that to print information when the serialEvent() callback gets called, to print what was read from the serial port, etc.

Is this with the arduino code or the Processing code.

It must have omething to do with how it's readin the serail monitor.

Processing doesn't read the serial monitor. If you have the serial monitor open, Processing can not connect to the serial port that the Arduino is writing to, so, of course it won't get any serial data.

Is this with the arduino code or the Processing code.

Where is the serialEvent callback?

The serialEvent callback is in the Processing code.

import processing.serial.*;
Serial myPort;
String sensorReading="";

PImage img;
PImage img2;


void setup() {
  size(1300, 1000);
   
        
  String portName = Serial.list()[0];

  img = loadImage("PLAN1.png");
  img2 = loadImage("PLAN2.png");
  
  myPort = new Serial(this, portName, 9600);
  myPort.bufferUntil('\r');
 
}

void draw() {
  
  
  
  if (sensorReading != null) {
     image(img, 0, 0);
     
  }
    
    
    if (sensorReading == null) { image(img2, 0, 0);
    
}
}  

void serialEvent (Serial myPort) {
  
  sensorReading = myPort.readStringUntil('\n');

  }

So how do I use the print() function to print the information when serialEvent() gets called? I tried various ways but can't seem to get it to work. It's showing PLAN1, PLAN2, PLAN1 and then just stopping. I tried changing != null to == "1" but that just showed no images at all. Is there any way to unvalue the sensorReading? What am I missing in the serialEvent callback in the code above? I've tried putting in various print() functions and loops but nothing is working. I've been at this for nearly 10 hours today! Sorry if I'm bothering you with all these questions.

What am I missing in the serialEvent callback in the code above?

Some debug statements.

I tried changing != null to == "1" but that just showed no images at all.

This would imply that no serial data is arriving. But, you don't know that, because there are no debug statements.

Is there any way to unvalue the sensorReading?

No. sensorReading always has a value. Sometimes that value is a NULL string, but it always has a value.

I've tried putting in various print() functions and loops but nothing is working.

What do you mean by "nothing is working"? If you put a println() statement in setup(), do you see the output at the bottom of the IDE window?

If so, then something is working. If not, then there is a real problem.

If you put println("Some serial data arrived"); in serialEvent, you can tell whether serial data is arriving. If you put
print("Serial string: [");
print(sensorReading);
println("]");
in serialEvent, you can see WHAT serial data arrived.

If you never see any of the messages from the serialEvent callback, but you do see the message from setup(), then we know something else.

Yes, it is printing at the bottom of the IDE, both from setup() and serialEvent.

print(sensorReading); also displays 1 or 2 depending on if there's light or not. So they both work. What isn't working is the images.

What do you mean by debug statements in the serialEvent?

This is what it's like now.

void serialEvent (Serial myPort) {
  
  sensorReading = myPort.readStringUntil('\n');
  
    print(sensorReading);
  
  }

The print(sensorReading) statement is a debug statement. It serves no purpose other than to help you debug the program.

By putting it there, you learned a lot. You learned that the Arduino IS communicating with Processing, and that the Processing application IS receiving what you expect. Although I don't like the idea of just printing raw data like that. In a more complex program, you won't know what raw data corresponds to what print statement.

I once debugged an application that was printing 4,000,000 lines of output before I figured out the problem. Without much more identifying data, I would still be trying to figure that problem out.

OK, so what does draw() look like, now? Please delete all the blank lines before posting. My scroll finger is getting quite a workout today, and is tired.

Oh right, I understand how the debugging works. It's printing 1 nd 2 in the right order anyway as it's running.

Ok, so the draw() method looks like this now

void draw() {
  if (sensorReading == "1") {
     image(img, 0, 0);
     }
 if (sensorReading == "2") {
       image(img2, 0, 0);
     }
}

and it's not working at all. It just shows a grey screen. sensorReading is printing 1 and 2 in the right order once it gets past NULL. So why isn't the draw working? Keep in mind that it worked earlier when I used (sensorReading != null). This is the part where I know something must be missing. I tried putting \r and \n and a few other things but it wont show the images unless its using (sensorReading != null).

The only other thing I can think to do is to add a print statement or two to draw() to see if something is happening to sensorReading after serialEvent ends.

If I add print statements to the draw() method like this.

void draw() {
  if (sensorReading == "1") {
     image(img, 0, 0);
print(sensorReading);
     }
 if (sensorReading == "2") {
       image(img2, 0, 0);
print(sensorReading);
     }
}

it still does nothing. Doesn't even print anything on the IDE.

If I add it into this version

void draw() {
  if (sensorReading != null) {
     image(img, 0, 0);
print(sensorReading);
     }
 if (sensorReading == null) {
       image(img2, 0, 0);
print(sensorReading);
     }
}

it changes the image the first 3 times and it keeps displaying the sensorReading for each one. The sensorReading continues to change when I turn off and on the light. But the image stays on PLAN2 after the first 3. There should be a way to fix this, I'm going crazy here trying to figure it out!

I might add that with the two print(sensorReading); added in the draw(), when it keeps displaying the sensorReading it puts a space between each one, like a line break and a blank. It looks something like this.

null
null
null
null
null
null
1
1

1

1

1

1

1

1

2

2

2

2