narner
narner

Reputation: 3241

Reading Arduino Serial Data with Processing

What I'm trying to do is read in a continuous stream of data from a tachometer circuit I made with Arudino, and then feed it into Processing; which I've successfully done using the code below:

What I'm not sure how to do is process the data so that whenever a certain value is detected, an event will occur in Processing.

EDIT: It was suggested by someone off SO that my problem was that the call to myMovie.loop() is a blocking call, which would mean that the instruction pointer in void setup() would stay on myMovie.loop(). The pointer would be making calls to void Draw() and movieEvent, but would never reach the lines where the serial port is initiated

port = new Serial(this, "/dev/tty.usbmodem1411", 9600); 
port.bufferUntil('\n');

The suggested solution was to move those those lines to the top of void Draw(), and have myMovie.loop as the last line of void setup(). I tried this (my code below reflects this change), but I'm still reading '0.0'in as serial input in Processing, but getting the correct data in Arduino.

Below is my Processing code:

import processing.video.*; 
import processing.serial.*; 


Serial port; 
Movie myMovie; 

//try as a float?
double val = 0; 

void setup() 
{  
 //create screen
 size(320, 240); 
 background(0); 
 //load movie
 myMovie = new Movie(this, "countdown.mov"); 


 // print a list of all available ports 
 println(Serial.list()); 

 // choose the port to which the Arduino is connected 
 // on the PC this is usually COM1, on the Macintosh 
 // this is usually tty.usbserial-XXX 
 port = new Serial(this, "/dev/tty.usbmodem1411", 9600); 


 ///(1) if this line used, no information is read
// port.bufferUntil('\n');  

 myMovie.loop(); 
}    




 void draw() { 
 if (0 < port.available()) { 

 ///(2) If this line is used, '0.0' is read once and displayed in serial output
 String strData = port.readStringUntil('\n'); // string representation of value

 //TEST
 print(val);

 val = Double.parseDouble(strData); // double from string data
}

 image(myMovie, 0, 0); 
}




void movieEvent(Movie m) {
 m.read();
if (val >= 3600) {
   myMovie.speed(1); 
}
else { 
   myMovie.speed(0); 
  }
}  

And below is my Arduino code:

 //// This example shows one way of creating an optoswitch
    //// using an IR LED as emitter and an IR LED receiver as
    //// light sensor.
    ////
    ////           + GROUND                                 +GROUND          
    ////           |                                        |  
    ////           <                                        < 
    ////           > 220 ohm resistor                       > 220 ohm resistor
    ////           <                                        <      
    ////           |                                        |  
    ////           |                                        |
    ////         -----                                    -----
    ////          / \    >>IR LED emitter >>>>>>>>>>>>>>>>  / \   IR LED receiver
    ////         -----                                    -----
    ////           |                                        |
    ////           |                                        |
    ////           + +5VCD                                  +  ANALOG INPUT 0
    ////
    ////
    ////
    ////<a href="http://playground.arduino.cc/Learning/Tachometer" target="_blank" rel="nofollow">http://playground.arduino.cc/Learning/Tachometer</a>


    int val;
    long last=0;
    int currentStatus=LOW;
    int previousStatus=LOW;
    int count=0;

    int sens=85;  // this value indicates the limit reading between dark and light,
                  // it has to be tested as it may change acording on the 
                  // distance the leds are placed.
    int nSpokes=7; // the number of blades of the wheel

    int milliseconds=500; // the time it takes each reading



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

    void loop()
    {
      val=analogRead(0);
      if(val<sens)
        currentStatus=LOW;
       else
        currentStatus=HIGH;
       digitalWrite(13,currentStatus); //as iR light is invisible for us, the led on pin 13 
                              //indicate the state of the circuit.

       if(previousStatus!=currentStatus){  //counts when the state changes from (dark to light) or 
                         //from (light to dark), remmember that IR light is invisible for us.
         count++;
         previousStatus=currentStatus;
       }
       if(millis()-last>=milliseconds){
         double rps=((double)count/nSpokes)/2.0*1000.0/milliseconds;
         double rpm=((double)count/nSpokes)/2.0*60000.0/(milliseconds);
    //     Serial.print((count/2.0));Serial.print("  RPS ");Serial.print(rps);
    //     Serial.print(" RPM");
    //     Serial.print(rpm);
    //     Serial.print("  VAL ");Serial.println(val); 
         Serial.println(rpm);
         count=0;
         last=millis();
       }
    }

Basically, I'm using an Arduino Uno to calculate the speed of a computer fan. If the fan stays at 3600 rpm, then I want a movie to play. If it drops below that, I want the movie to stop playing. My Arduino sketch is working (I'm able to read in the data fine on the serial port), but for some reason I can't do that with Processing; no data appears to be coming in. I based this off of the serial examples included with Arduino, but nothing seems to work yet.

Upvotes: 0

Views: 1576

Answers (2)

Lex
Lex

Reputation: 2096

I think you have multiple problems here and need to separate them slightly. The first thing I would do is remove the arduino from the equation for now and verify that the processing side of things works properly first. Have the processing sketch simply pretend to itself that it is getting the right data for now and then you can more easily figure out if you have any blocking issues. The next thing to do is to sort out the photodiode circuit. From what I gather, you have a resistor between ground and the 'cathode' on the photodiode, you then have the anode attached to the analog input. I'm fairly sure this won't work.

The way it should work (I think) is that you connect your anode to ground and your cathode to the analog input pin. Then connect that same analog input pin to your power supply voltage via a fairly high resistance. (somewhere in the order of megaohms). By doing this, you have the analog input at the supply voltage when it is dark as the photodiode is reversed biased and is not producing a voltage. When there is light, there will be a small amount of current allowed through the diode, with a large enough resistor, this current to ground will cause a small volt drop to appear across the diode and so you will measure a slightly lower value on your input. I think that should work. There is also a difference between a photodiode and a phototransistor, make sure you know which one you have, a photodiode should also work in the circuit described where the collector replaces the cathode and the emitter replaces the anode. This may need a smaller resistor on the collector side however, 1MOhm and beyond would be too high, somewhere around 1k. of course, if you are sure you have a photodiode then this doesn't matter.

But this is all just me guessing (ish). I've not used photodiodes or phototransistors much.

Once you are sure you are getting good values from the arduino/photodiode side of things, and you know that you have a working processing sketch, then you can try and connect the two.

Upvotes: 1

Theoneil Steenkamp
Theoneil Steenkamp

Reputation: 21

Try print(val); in the void draw() function to see if any values gets sent to the console. I'm guessing that val never changes from 0.

Also I don't think you should use both port.bufferUntil('\n'); and port.readStringUntil('\n');

Try only one at a time. Not sure if that makes a difference but in the docs they only use one at a time that I could see.

I would also change

 if (val == 0) { 
   myMovie.speed(0); 
 } 
 else if (val >= 3600) 
   myMovie.speed(1); 
 else { 
   myMovie.speed(0); 
 }

to

if (val >= 3600) {
   myMovie.speed(1); 
}
else { 
   myMovie.speed(0); 
}

Hope this helps.

Upvotes: 0

Related Questions