Go Down

Topic: controlling an image sequence in processing with adruino (Read 3818 times) previous topic - next topic

ettaler18

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!

PaulS

Quote
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.
The art of getting good answers lies in asking good questions.

ettaler18

#2
Jan 29, 2012, 03:43 pm Last Edit: Jan 29, 2012, 05:43 pm by ettaler18 Reason: 1
thank you for your reply
my processing code is




Code: [Select]
// 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)


Code: [Select]

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,


ettaler18

#3
Jan 29, 2012, 03:58 pm Last Edit: Jan 29, 2012, 05:44 pm by ettaler18 Reason: 1
here`s a new version of my adruino code
Code: [Select]

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); //


 }

PaulS

#4
Jan 29, 2012, 04:25 pm Last Edit: Jan 29, 2012, 04:26 pm by PaulS Reason: 1
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.

Code: [Select]
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:
Code: [Select]
import processing.serial.*;

Define an instance of the serial library:
Code: [Select]
Serial myPort;

Initialize the instance and tell the serial object to buffer data until something interesting happens (in setup()):
Code: [Select]
 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:
Code: [Select]
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.
Code: [Select]
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.
The art of getting good answers lies in asking good questions.

ettaler18

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

PaulS

You currently have something like this:
Code: [Select]
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:
Code: [Select]
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.
The art of getting good answers lies in asking good questions.

PaulS

If that code produces flicker, change imageIndex to currImageIndex. Add
Code: [Select]
int prevImageIndex = -1;
immediately after the declaration of currImageIndex.

Then, draw() would look like:
Code: [Select]
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.
The art of getting good answers lies in asking good questions.

ettaler18

Thank you for your effort
Now it looks like this,but the code doesn`t work properly.
Code: [Select]
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);
}


PaulS

What is this supposed to be doing? It is not inside a function.
Code: [Select]

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


Code: [Select]
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?

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

"Change imageIndex to currImageIndex" is not the same as "Add another variable named currImageIndex".
The art of getting good answers lies in asking good questions.

ettaler18

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
Code: [Select]

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);
 }
}



PaulS

You still aren't getting the currImageIndex value from the serial string.
The art of getting good answers lies in asking good questions.

ettaler18

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

ettaler18

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

PaulS

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

Processing has a reference page: http://processing.org/reference/
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.
The art of getting good answers lies in asking good questions.

Go Up