用处理读取Arduino串行数据

时间:2014-09-09 20:36:49

标签: serial-port arduino processing microcontroller arduino-uno

我尝试做的是从Arudino制作的转速计电路连续读取数据,然后将其输入Processing;我使用以下代码成功完成了这项工作:

我不确定如何处理数据,以便每当检测到某个值时,处理中都会发生事件。

编辑:有人建议说我的问题是对myMovie.loop()的调用是阻塞调用,这意味着void setup()中的指令指针留在myMovie.loop()。指针将调用void Draw()movieEvent,但永远不会到达启动串行端口的行

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

建议的解决方案是将这些行移到void Draw()的顶部,并将myMovie.loop作为void setup()的最后一行。我尝试了这个(我的代码在下面反映了这一变化),但我仍在阅读'作为处理中的串行输入,但在Arduino中获取正确的数据。

以下是我的处理代码:

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

以下是我的Arduino代码:

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

基本上,我使用Arduino Uno来计算电脑风扇的速度。如果风扇保持在3600转,那么我想要一部电影。如果它低于那个,我希望电影停止播放。我的Arduino草图正在工作(我能够在串口上读取数据很好),但出于某种原因,我无法通过Processing执行此操作;似乎没有数据出现。我的基础是Arduino附带的序列示例,但似乎没有任何工作。

2 个答案:

答案 0 :(得分:1)

我认为你在这里遇到了很多问题,需要稍微分开。 我要做的第一件事就是暂时从等式中删除arduino并验证事物的处理方面是否正常工作。让处理草图简单地假装它现在正在获取正确的数据然后你可以更容易地弄清楚你是否有任何阻塞问题。 接下来要做的是整理光电二极管电路。从我收集到的,你在地面和阴极之间有一个电阻器。在光电二极管上,然后将阳极连接到模拟输入。我确信这不会奏效。

它的工作方式(我认为)是您将阳极连接到地,阴极连接到模拟输入引脚。然后通过相当高的电阻将相同的模拟输入引脚连接到电源电压。 (某处兆欧的数量级)。通过这样做,当光电二极管反向偏置并且不产生电压时,在暗处时,模拟输入处于电源电压。当有光时,通过二极管会有少量电流,电阻足够大,这个接地电流会在二极管上产生一个小的电压降,所以你会测量一个稍低的值。输入。 我认为这应该有效。 光电二极管和光电晶体管之间也存在差异,确保您知道自己有哪一个,光电二极管也应该在所描述的电路中工作,其中集电极取代阴极,发射极取代阳极。这可能需要在集电极侧使用更小的电阻,但是1MOhm以及更高的电阻会太高,大约1k左右。当然,如果你确定你有一个光电二极管那么这并不重要。

但这只是我的猜测(ish)。我没有太多使用光电二极管或光电晶体管。

一旦你确定你从arduino /光电二极管方面获得了很好的价值,而且你知道你有一个正常工作的处理草图,那么你可以尝试连接两者。

答案 1 :(得分:0)

在void draw()函数中尝试print(val);以查看是否有任何值发送到控制台。 我猜测val永远不会从0变化。

另外,我认为你不应该同时使用port.bufferUntil('\n');port.readStringUntil('\n');

一次只尝试一个。不确定这是否有所不同,但在文档中他们只能一次使用一个我能看到的。

我也会改变

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

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

希望这有帮助。