controlling an image sequence in processing with adruino

Hey guys!How can I connect the values from the distant sensor to the 510 pictures I have in processing,so that I can fill my glass of beer by going up with my hand.Thank you for your help!

How can I connect the values from the distant sensor to the 510 pictures I have in processing,so that I can fill my glass of beer by going up with my hand.

Depends on the Arduino code you have for reading the sensor, and the Processing code that you have for reading serial data.

There are examples provided with both Processing and Arduino that show how to send/receive serial data.

Making Processing use that serial data to determine which picture to show is up to you. How that relates to filling your beer glass is a mystery.

thank you for your reply
my processing code is

// Example 15-4: Image sequence

int maxImages = 510; // Total # of images
int imageIndex = 0; // Initial image to be displayed is the first

// Declaring an array of images.
PImage[] images = new PImage[maxImages];

void setup() {
  size(320,240);
  
  // Loading the images into the array
  // Don't forget to put the JPG files in the data folder!
  for (int i = 0; i < images.length; i ++ ) {
    images[i] = loadImage( "picture" + i + ".png" ); 
  }
  frameRate(50);
}

void draw() {
  
  background(0);
  image(images[imageIndex],0,0);
  
  // increment image index by one each cycle
  // use modulo " % "to return to 0 once the end of the array is reached
  imageIndex = (imageIndex + 1) % images.length;
}

my adruino code is (until now)

int analogPin1 = A5;





void setup() // run once, when the sketch starts
{
  //mySerial.begin(9600);
  
  pinMode(analogPin1, INPUT);
  Serial.begin(9600);

} 


void loop() // run over and over again
{

  Serial.println(analogRead(A5));
  delay(100); //
 

  }

but I don`t have a connection up to know,

here`s a new version of my adruino code

int analogPin1 = A5;

int val;



void setup() // run once, when the sketch starts
{
  Serial.begin(9600);
  
  pinMode(analogPin1, INPUT);
  Serial.begin(9600);

} 


void loop() // run over and over again
{
val = analogRead(A5);
val = map(val, 30, 600, 0, 510);
  Serial.println(analogRead(A5));
  delay(100); //
 

  }

There is an icon, just above the smiley faces, with # on it. That icon should be clicked before posting code. "Why?", you ask. Does your code really look like this:
images = loadImage( "picture" + i + ".png" );

I hope not.

val = analogRead(A5);
val = map(val, 30, 600, 0, 510);
  Serial.println(analogRead(A5));

You read an actual value, map that to the range 0 to 510, then read another value and send that one. So, what is the map() doing for you?

In your Processing sketch, you need to do several things.
Import the serial library:

import processing.serial.*;

Define an instance of the serial library:

Serial myPort;

Initialize the instance and tell the serial object to buffer data until something interesting happens (in setup()):

  myPort = new Serial(this, Serial.list()[2], 2400);
  // tell the serial port not to generate a serialEvent
  //until a linefeed is received:
  myPort.bufferUntil('\n');

You can print the list of COM ports that Processing knows about:

println(Serial.list());

so that you can use the correct index - 2 in my case, but it may not be in your case.

add a serialEvent() method.

void serialEvent(Serial myPort)
{
  // Read the serial data
  String myString = myPort.readStringUntil('\n');
}

The Arduino code uses Serial.println(), so the value is followed by the carriage return. Processing will buffer data until the carriage return arrives. When it does, it will fire the serialEvent callback.

In that callback, you read the value as a String. Then, you need to convert the value in the String object to an integer, and store the integer in a global variable.

In the draw() function, quit iterating through the images. Instead, draw just the one image whose index is stored in the global variable. To reduce flicker, keep another (global) variable that contains the last image index, and do not redraw if the previous and current index is the same.

Thank you for the detailed answer.I just dont get the last point where you explain how to go through the images. Would be nice if you could give an example code because Im quite desperate.

You currently have something like this:

void draw() {
 
  background(0);
  image(images[imageIndex],0,0);
 
  // increment image index by one each cycle
  // use modulo " % "to return to 0 once the end of the array is reached
  imageIndex = (imageIndex + 1) % images.length;
}

That should be:

void draw()
{
  background(0);
  image(images[imageIndex],0,0);
}

where imageIndex is set in the serialEvent() callback, based on the integer extracted from the String object.

If that code produces flicker, change imageIndex to currImageIndex. Add

int prevImageIndex = -1;

immediately after the declaration of currImageIndex.

Then, draw() would look like:

void draw()
{
  if(currImageIndex != prevImageIndex)
  {
    background(0);
    image(images[currImageIndex],0,0);
    prevImageIndex = currImageIndex;
  }
}

The first time draw() runs, 0 is not equal to -1l so images[0] will be drawn. Then, prevImageIndex and currImageIndex will contain the same value, so nothing will be drawn until serial data is received. If the value received is not 0, the new image will be drawn, and prevImageIndex will be set to the index that was drawn, so nothing will be drawn again until a new (and different) value is received from the serial port.

Thank you for your effort
Now it looks like this,but the code doesn`t work properly.

import processing.serial.*;
Serial myPort;




int maxImages = 510; // Total # of images
int imageIndex = 0; // Initial image to be displayed is the first
int prevImageIndex = -1;
int currImageIndex;
// Declaring an array of images.
PImage[] images = new PImage[maxImages];

void setup() {

  myPort = new Serial(this, Serial.list()[1], 9600);
  // tell the serial port not to generate a serialEvent
  //until a linefeed is received:
  // myPort.bufferUntil('\n');
  size(320, 240);

  // Loading the images into the array
  // Don't forget to put the JPG files in the data folder!
  for (int i = 0; i < images.length; i ++ ) {
    images[i] = loadImage( "picture" + i + ".png" );
  }
  frameRate(50);
}
void serialEvent(Serial myPort)
{
  // Read the serial data
  String myString = myPort.readStringUntil('\n');
}
void draw() 

{
  if (currImageIndex != prevImageIndex)
  {
    background(0);
    image(images[currImageIndex], 0, 0);
    prevImageIndex = currImageIndex;
  }
}

{
  background(0);
  image(images[imageIndex], 0, 0);
}

What is this supposed to be doing? It is not inside a function.

{
  background(0);
  image(images[imageIndex], 0, 0);
}
void serialEvent(Serial myPort)
{
  // Read the serial data
  String myString = myPort.readStringUntil('\n');
}

So, you may or may not ever see this function called. If you do, you store the data in a local variable that goes out of scope immediately. Where is the code you were supposed to add to convert the value in myString to an int that is stored in currImageIndex?

If that code produces flicker, change imageIndex to currImageIndex.

"Change imageIndex to currImageIndex" is not the same as "Add another variable named currImageIndex".

yea I just have seen that one code was not inside the draw function.So now I put it into the draw function and also changed ImageIndex to currImageindex
but it still doesn`t work properly

import processing.serial.*;
Serial myPort;




int maxImages = 510; // Total # of images
int currImageIndex = 0; // Initial image to be displayed is the first
int prevImageIndex = -1;

// Declaring an array of images.
PImage[] images = new PImage[maxImages];

void setup() {

  myPort = new Serial(this, Serial.list()[1], 9600);
  // tell the serial port not to generate a serialEvent
  //until a linefeed is received:
  // myPort.bufferUntil('\n');
  size(320, 240);

  // Loading the images into the array
  // Don't forget to put the JPG files in the data folder!
  for (int i = 0; i < images.length; i ++ ) {
    images[i] = loadImage( "picture" + i + ".png" );
  }
  frameRate(50);
}
void serialEvent(Serial myPort)
{
  // Read the serial data
  String myString = myPort.readStringUntil('\n');
}
void draw() 

{
  if (currImageIndex != prevImageIndex)
  {
   
  background(0);
  image(images[currImageIndex], 0, 0);
  }
}

You still aren't getting the currImageIndex value from the serial string.

I want to do it,but I`m not sure how to change the code properly.

is there a possibility to make it as a map function?
But Im not sure how to use that either,Im just a beginner.

I want to do it,but I`m not sure how to change the code properly.

Processing has a reference page: Reference / Processing.org
There is a section for String functions. Look at the split() function, specifically the second example, for a hint.

The int() function is what you want to use.

Ok,the code was totally messed up,so I structured it and worked on it.Now the ardruino code works as well as the processing code.
But no images are displayed and I can`t find a fault.Can you find it?
This is the actual processing code:

/*

 
 */

import processing.serial.*;

// Variables for putting image sequences on screen.
int imagewidth = 320;
int imageheight = 240;
int numPics = 510;

float highValue = 0;
float average;
int sequences = 0;

// Variables for serial connection.
char header = 'A'; // For controlling the carriage return and bla... bla... bla...
int NEWLINE = 10;
float value;
String buff = ""; // Buffing :P

Serial port;

PImage[] beer = new PImage[numPics];

void setup() {
  size(imagewidth, imageheight);
  imageMode(CENTER);

  // Initializing the image sequences.
  for (int i = 0; i < beer.length; i++) {
    println(i);
      beer[i] = loadImage("picture"+ i +".png");
     
    }
  

  // Establish connection to Serial port.
  println(Serial.list()); // Formality.
  port = new Serial(this, Serial.list()[0], 9600); // Establish Serial connection.
}

void draw() {
 
 
  // Checking the highest value.
  if (value > highValue) {
    highValue = value;
    average = highValue / 2;
  }
  
  if(value > average){
    sequences++;
    
    if(sequences > numPics - 1){
      sequences = 0;
    }
    
    
    // Debug.
    println("Increased");
  }
  else if(value < highValue){
    sequences--;
    
    if(sequences < 0){
      sequences = numPics - 1;
    }
    
    // Debug.
    println("Decreased");
  }
  


  // Debug.
  // println(i);

  // From connection to Serial ports.
  while (port.available () > 0) {
    serialEvent(port.read());

    // Debug.
     println(port.read());
  }
  
  delay(50);

  // Debug.
  // println(value);
}

void serialEvent(int serial) {
  try {
    if (serial != NEWLINE) {
      buff += char(serial);
    }
    else {
      char c = buff.charAt(0);
      buff = buff.substring(1);
      buff = buff.substring(0, buff.length() - 1);
      if (c == header) {
        value = Integer.parseInt(buff);
      }

      buff = "";
    }
  }
  catch(Exception e) {
    println("no valid data");
  }
}
  // From connection to Serial ports.
  while (port.available () > 0) {
    serialEvent(port.read());

    // Debug.
     println(port.read());
  }

What?

The only thing wrong with the code that you had was that you were not doing anything with the serial data. Now, you are, but you are doing it all wrong. port.read() gets one byte.

Get rid of this stuff. Put serialEvent() back the way it was, and add:
currImageIndex = int(myString);
after the code to read the string.

You might want to print myString and currImageIndex in the serialEvent method, to confirm that all is working.

Okay,thank you for the advice.did I get it right that I need to take the last code and just have to change the serial event like this :

void serialEvent(Serial myPort)
{
  // Read the serial data
  String myString = myPort.readStringUntil('\n');
  currImageIndex = int(myString);
}
void draw() 

{
  if (currImageIndex != prevImageIndex)
  {
   
  background(0);
  image(images[currImageIndex], 0, 0);
  }
}

now the first picture loads,but no further pictures.
Why?

now the code works :slight_smile:
thank you for your help!

So, what happened between 10:42 and 11:55?