duminică, 6 octombrie 2013


Arduino si Processing – comunicare seriala

 Pe net , se gãsete literaturã suficientã, tutoriale şi exemple privind comunicarea serialã intre placa duino şi PC. Una din variantele cele mai accesibile de abordat este Processing 2.0. O sa postez câteva din încercãrile mele , care au funcţionat, fãrã prea multe referiţe teoretice .Doar strictul nrcesar pentru cine vrea sã încerce. 
1.Date de la Arduino la Processing :
- am încãrcat în Arduino Uno sketch-ul “serialAut”:
............................................................................................................ 
/* serialAut – trimite secvental la ‘serialIn’ din Processing  expresia “Hello World!”
Pe portul serial Com3 – in cazul meu */

 void setup()
{
// initialize serial communications at a 9600 baud rate
Serial.begin(9600);
}
void loop()
{
// trimite  'Hello, world!'  la portul serial
Serial.println("Hello, world!");
      //asteaptã  100 millisecunde
delay(100);
}
........................................................................................................................ 
Dupa încãrcarea pe Arduino şi verificarea în Serial Monitor , programul Arduino
1.0  poate fi oprit. Afişarea stringulu transmis se face în Processing 
Programul din Processing care peia datele serial de la Com3 trimise de Arduino:
……………………………………………………………………………………………………..
//serialIn.pde
import processing.serial.*;
//merge !
Serial myPort;   // Creazã un obiect din clasa Serial
String val;         // reţine datele primate de la portul seria
  // aflat în lista Serial.list()[0].  In  Windows, la mine se      //deschid COM1 şi COM3. In Processing primul port deschis //apare cu (0) iar al doilea cu (1)
void setup(){
String portName = Serial.list()[1]; //schimb  0 la 1
//sau portul pe care lucreazã Arduino !
myPort = new Serial(this, portName, 9600);
}
void draw(){
  if ( myPort.available() > 0)  {  // daca au intrat date pe port,
       val = myPort.readStringUntil('\n');   
     // le citeşte şi le preia în  variabila val
  }
println(val);      //print it out in the console
}
………………………………………………………………….
Datele preluate (Hello World) sînt afişate în partea de
jos a interfeţei Processing.
2.Date transmise de la Processing la Arduino
In acest exemplu, sketch-ul “ardIn” primeşte caracterul 1 trimis din Processing de la  “outPro”. Dacã facem click  (sau ţine apasat  butonul stânga mouse) în mini displayul afişat de Processing la rulare, ledul de la pin 13 se aprinde.



3.Comunicare bilaterala (partea 1)  “Shaking Hands”
 Până acum am arătat că Arduino și Processing pot comunica serial atunci când unul “vorbește” și celălalt  “ascultã”. Putem face un link care permite datelor să circule în ambele sensuri, astfel încât Arduino și Processing sa trimita  și sa primeasca date?
 În biz acest lucru este denumit “Shaking Hands” (strângere de mână) , deoarece ambele părți trebuie să fie de acord atunci când  trimit și primesc  date.
Pe aceasta paginã și următoarea, vom combina cele două exemple  anterioare, în așa fel încât Processing poate primi  "Bună ziua, lume!" de la Arduino și poate trimite un 1 înapoi la Arduino pentru a comuta un LED.
Desigur, acest lucru înseamnă, de asemenea, că Arduino trebuie să fie capabil să trimită "Bună ziua, lume!" în timp ce asculta pe portul serial  pentru a primi  un 1 de la Processing. !
Să începem cu partea Arduino a lucrurilor. Pentru ca acest lucru să ruleze fără probleme, ambele părți trebuie să știe ce să asculte și ce trebuie sã trimitã  cealaltă parte, ce așteaptă să audă.
 De asemenea, dorim să reducem la minimum traficul de pe portul serial așa ca sã putem obține mai multe răspunsuri în timp util.
Avem nevoie de o variabilă pentru datele noastre de intrare și o variabilă pentru pinul LED pe care  dorim sa îl  aprindem. In Arduino se încarca scriptul   arduWR.ino:
………………………………………………………………………………………….
/*  arduWR   */
char val;                                          //retine data receptionata de la portul serial
int ledPin = 13;                                // seteaza    pin-ul 13 pentru pentru led  
boolean ledState = LOW;                             // retine starea LED-ului si o initializeaza LOW
void setup()
{
  pinMode(ledPin, OUTPUT);             // seteaza  pinul  ca  OUTPUT
                                                      //initializeaza comunicarea seriala la 9600 baud
  Serial.begin(9600);
  establishContact();  // trimite un byte pentru a stabli contactul atit timp cit  recetorul raspunde
}
void loop()
{
  if (Serial.available() > 0) {    // daca datele sint disponibile pt a fi citite
   val = Serial.read();            //  citeste si le preia in variabila  val
   if(val == '1')                      //daca a fost  trimis ‘1’
    {
       ledState = !ledState;     // comuta starea anterioara a LED-ului: dca a fost stins il aprinde, si invers
       digitalWrite(ledPin, ledState);
    }
    delay(100);                
  }
    else {
    Serial.println("Hello, world!");         //altfel daca nu este ‘1’ trimite inapoi sirul hello world
    delay(50);
    }
}
void establishContact() {
  while (Serial.available() <= 0) {
  Serial.println("A");   // trimite caracterul   A
  delay(300);
  }
}
………………………………………………………………………………………………………..
 In Processing , se editeaza / deschide scriptul “procWR
…………………………………………………………………..
//procWR
 import processing.serial.*; //import the Serial library
 Serial myPort;  //the Serial port object
 String val;   // deoarece facem “serial handshaking”,
// este nevoie sa verificam ce auzim de la microcontroller
boolean firstContact = false;
void setup() {
  size(200, 200);       //make our canvas 200 x 200 pixels big
                               //  initialize your serial port and set the baud rate to 9600
  myPort = new Serial(this, Serial.list()[1], 9600);
  myPort.bufferUntil('\n');
}
void draw() { //  putem pstra metoda draw goala
                   // pentru că toate programul nostru se petrece în serialEvent (vezi mai jos)}
void serialEvent( Serial myPort) {
// preia data sosita intr-un String
// '\n' este delimitatorul   final, care indica sfirsitul pachetului de date care a fost primit  complet
val = myPort.readStringUntil('\n');
// verificam daca datele noastre nu sint nule , inainte de a continua
if (val != null) {
                  //eliminam  spațiile goale și caracterele de formatare (cum ar fi retur de car)
  val = trim(val);
 println(val);
      // ne uitam dupa șirul  "A"  noastre pentru “start the handshake”
       //daca sirul ‘a’ este prezent, golim  the buffer-ul , si trimitem o cerere de date ( request for data)
  if (firstContact == false) {
    if (val.equals("A")) {
      myPort.clear();
      firstContact = true;
      myPort.write("A");
      println("contact");
    }
  }
  else { // daca am stability udeja un contact, pastram achizitia si preluam datele si le analizam
    println(val);
    if (mousePressed == true)
    {                           //if we clicked in the window
      myPort.write('1');        //send a 1
      println("1");
    }

                              // when you've parsed the data you have, ask for more:
    myPort.write("A");
    }
  }
}
…………………………………………………………………………………………..
Cu board-ul Arduino cuplat la portul serial ( si avind montat LED-ul cu resistor la pin13), se ruleazã “procWR” cu Processing 2 .
 La rularea programului , la click-uri consecutive  în miniDisplay-ul deschis din Processing, LED-ul se aprinde şi se stinge.
Atentie : dacã portul serial este scris corect în Processing, totul merge din prima încercare !
Porturile în Processing sunt numerotate cu 0; 1; 2; 3. Eu am pus 1 pentru cã am douã porturi active : Com1 şi COM3. La mine în PC, portul  COM3 este al doilea port serial si se deschide când cuplez boardul Arduino