Arduino e GUI Processing

Salve a tutti,Sono alle prese con la realizzazzione di un interfaccia per la gestione del mio arduino.
L'interfaccia prevede l'attivazione di un motore.Quando il motore viene attivato allora appaiono dei valori presi dall'arduino.Fin qui tutto bene.Sto cercando di implementare la funzione che se nel caso il motore sia stato attivato esternamente dall'arduino , la GUI deve gia mostrarmi l'interfaccia con i valori.
Ho realizzato i codici in questa maniera

Processing
http://nopaste.info/5230cf8c1a_nl.html

Arduino
http://nopaste.info/7f6ca43846_nl.html
Se il motore viene attivato esternamente attiva chiude un collegamento tra un pin e la 5v così arduino capisce che il motore è attivo.Ritorno il valore alla GUI che con un if attiva o disattiva l'interfaccia con i valori.
Dove sbaglio? Ho provato a inserire una scritta di controllo( text(statomotore, 160, 300); ) per vedere se il valore viene tornato bene alla gui ma rimane sempre 0 nella gui.

Non uso Processing e non faccio interfacce HTML per l'Arduino però una cosa la capisco: senza codice, come possono darti un aiuto le persone che potrebbero farlo? Su cosa si basano per analizzare il problema? :wink:

I codici di arduino e processing li ho messi in quei due link a nopaste.Li ho dovuti mettere necessariamente li visto che la board mi diceva che il messaggio superava i caratteri massimi con cui scrivere il post

In questo caso devi usare l'Hyperlink per inserire l'indirizzo (seconda riga, terzo pulsante sotto la U di underline)

URL messi a posto.

Dove hai messo la text(statomotore, 160, 300); di prova, nella serialEvent?
Nell'help di processing dice:
void serialEvent(Serial p) {
inString = p.readString(); // uso p, non myPort
}
Magari è uguale, ma proverei come dice l'help

francescoprisco:
I codici di arduino e processing li ho messi in quei due link a nopaste.Li ho dovuti mettere necessariamente li visto che la board mi diceva che il messaggio superava i caratteri massimi con cui scrivere il post

Un suggerimento per le volte successive: basta mettere i file in uno ZIP ed allegarlo al tuo post, senza usare servizi esterni che poi, per problemi di link, non possono essere raggiunti :wink:

Leo grazie per il consiglio del ZIP.Per quando riguarda inString = p.readString(); gli altri valori me li restituisce correttamente anche con inString = (myPort.readString());
Intanto però dopo provo giusto per sicurezza.Per quando riguarda

Dove hai messo la text(statomotore, 160, 300); di prova, nella serialEvent?

Ho messo quel valore come tutti gli altri.Lo trovi qui statomotore=sensors[5];

Facendo delle prove con il tuo codice, spedisco dati da un mio programma in VB6.
Ho letto nell'help di Processing che la serialEvent scatta a seconda di come metti i parametri, ad esempio usando la bufferUntil

Nel mio Processing l'evento scatta ma mi trovo sempre dentro a inString solo ultimo carattere.
Ho riprovato usando buffer(). Se devo spedire 1,2,3,4,5 ovvero 9 caratteri, allora nella setup()

  myPort.buffer(9);   // myPort.bufferUntil(lf);

Magari il problema è cosa spedisce arduino con la println -> fine stringa? carattere 10? oppure 13 new line?
Se usi la print("A") invii solo A ma se fai println("A") invii A più il newline che dipende (credo) dal sistema. Su win credo 10+13 su linux 10 (credo)
La myPort.bufferUntil(lf); dove lf è 10, la serialEvent si attiva se arriva il 10 ma non son sicuro arrivi con la println di Arduino

Prints data to the serial port as human-readable ASCII text followed by a carriage return character (ASCII 13, or '\r') and a newline character (ASCII 10, or '\n'). This command takes the same forms as Serial.print().

Ho spedito da mio programma VB la stringa 1,2,3,4,5,6, (12 caratteri) e ho modificato Processing così:

...nella setup

 myPort = new Serial(this, Serial.list()[0], 9600); 
 myPort.clear();
 myPort.buffer(12); //inString = myPort.readStringUntil(lf);
 inString = null;

...nella draw

void draw() 
{ if(inString!=null) InfoDati();
  // println(statomotore);  per debug
  if(statomotore!=0) 
  ...

...la serialEvent

void serialEvent(Serial p) 
{ inString = (p.readString()); 
  // println("prova"+inString);  per debug
}

void InfoDati()   // traduce i dati ricevuti, è critica perchè bisogna essere sicuri di ricevere esattamente 6 valori terminati da ,
{ int sensors[] = int(split(inString, ',')); 
  primazona=sensors[0]; 
  secondazona=sensors[1]; 
  terzazona=sensors[2]; 
  numgiri=sensors[4]; 
  statomotore=sensors[5]; 
  float sensorss[] = float(split(inString, ',')); 
  velocita=sensorss[3];
  inString=null; 
}

Ho usato anche VirtualSerialPortEmulator per spedire dati da VB a Processing usando la stessa porta. Non avevo voglia di farlo da Arduino.
Spero che da Arduino spedisci 6 cifre terminate da ,

Con queste modifiche la tua interfaccia si "anima".

Non funziona nulla.Iniziano ad uscire valori a caso e comunque l'interfaccia non si anima.
Il codice l'ho messo così

// Example by Tom Igoe

import processing.serial.*;

//IMPOSTAZIONI GRAFICHE//
////////////////////////////////////////////////////
int width=800;
int height=600;

int button1X;
int button1Y;
int button2X;
int button2Y;
int button3X;
int button3Y;
boolean button1Over = false;
boolean button2Over = false;
boolean button3Over = false;
int button1Width = width/10;
int button1Height = height/20;
int button2Width = button1Width;
int button2Height = button1Height;
int button3Width = button1Width;
int button3Height = button1Height;
float buttonFont = button1Height/1.5;
float wordFont = button1Height;
color buttonColor, buttonHighlight, buttonPressed;
PFont font;
PFont fontnumber;
PFont fontfirma;
/////////////////////////////////////////////////
////////////////////////////////////////////////////
int statomot=0;
float velocita;
int primazona = 0;
int secondazona=0;
int terzazona=0;
float periodo=0;
float carrpass=0;
int tempo=5;
int car=100;
int numgiri=0;
int numcar=0;
int statomotore=0;
////////////////////////////////////////////////////
//END//
Serial myPort;    // The serial port
// The display font
String inString;  // Input string from serial port
int lf = 10;      // ASCII linefeed
////////////////////////////////////////////////////
void setup() {
  ////////////////////////////////////////////////////////
  size(width, height);
  smooth();
  font = loadFont("Aharoni-Bold-48.vlw");
  fontnumber = loadFont("DS-Digital-48.vlw");
    fontfirma = loadFont("Windsong-48.vlw");
  buttonColor = color(255);
  buttonHighlight = color(200);
  buttonPressed = color(50);
  button1X = width/10 - button1Width/2;
  button1Y = height/5 - button1Height/2;
  button2X = 2*width/10 - button1Width/2;
  button2Y = height/5 - button1Height/2;
  button3X = 3*width/10 - button1Width/2;
  button3Y = height/5 - button1Height/2;
  textFont(font, 18);
////////////////////////////////////////////////////
 // println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600);
 myPort.bufferUntil(lf);
//////////////////////////////////////////////////////
myPort.clear();
 myPort.buffer(20); //inString = myPort.readStringUntil(lf);
 inString = null; 
}

void draw() {
   if(inString!=null) InfoDati();
 if(statomotore!=0)
  {
    statomot=1;
    }
  background(200);
  noFill();
  stroke (255);
  strokeWeight(2);
  rect(width/25, height/13, 300, 300);
  strokeWeight(2);
  rect(width/2.3, height/13, 405, 300);
  strokeWeight(2);
  rect(width/25, height/1.6, 720, 175);
  update(mouseX, mouseY);


  if (button1Over) {
    fill(buttonHighlight);
  } 
  else {
    fill(buttonColor);
  }
  stroke(0);
  rect(width/1.52, height/2.43, 155, 35);

  if (button2Over) {

    
    if(statomot==0)
    {
fill(100,200,0);
    }else if(statomot==1)
    {
    fill(255,0,0);
    }
  } 
  else {
    fill(buttonColor);
  }
  stroke(0);
  rect(width/1.72, height/5.8, 132, button2Height);

  if (button3Over) {
    fill(buttonHighlight);
  } 
  else {
    fill(buttonColor);
  }
  stroke(0);
  rect(377, 246, 134, 35);




  textFont(font, buttonFont);
  textFont(font, wordFont);
  fill(0);
  text("Produzione", width/20, height/8);
  fill(0);
  text("Controllo Motore", width/1.9, height/8);
  fill(0);

  if (statomot==0)
  {
    text("Accendi", width/1.7, button1Y + button1Height/1.3);
  }
  else if (statomot==1)
  {
    text("Spegni", width/1.7, button1Y + button1Height/1.3);
  }

  text("Velocita'", width/1.7, height/2.9);
  text("Aumenta", width/2.1, height/2.2);
  text("Diminuisci", width/1.5, height/2.2);
  textFont(font, wordFont);
  fill(0);
 if(statomot==0)
  {
   text("Motore Spento", 80, 130);
   }else if(statomot==1)
   {
  text("Carrelli", 80, 130);
  text("Prima zona: ", 40, 180);
  textFont(fontnumber, 40);
  text(primazona, 211, 180);
  textFont(font, wordFont);
  text("Seconda zona: ", 40, 220);
  textFont(fontnumber, 40);
  text(secondazona, 250, 220);
  textFont(font, wordFont);
  text("Terza zona: ", 40, 260);
  textFont(fontnumber, 40);
  text(terzazona, 208, 260);
  textFont(font, wordFont);
  text("Velocita': ", 40, 300);
  textFont(fontnumber, 40);
  text(velocita, 160, 300);
}
  if(statomot==0)
  {
   text("Motore Spento", 40, 440);
   text(statomotore, 160, 300);
   }else if(statomot==1)
   {
  periodo=(2*3.14*13.5)/velocita;
  carrpass=(tempo*car)/periodo;
  textFont(font, wordFont);
  text("Statistiche", 40, 405);
  text("In ogni giro di motore devono passare ", 40, 440);
  textFont(fontnumber, 40);
  text(numcar, 600, 440);
  textFont(font, wordFont);
  text("Attualmente sono stati effettuati ", 40, 470);
  textFont(fontnumber, 40);
  text(numcar, 510, 470);
  textFont(font, wordFont);
  text("giri di motore", 540, 470);

 }
  textFont(font, 30);
      text("© 2013 Created by", 40, 590);
      textFont(fontfirma, 48);
      text("Francesco Prisco",300, 590);
      textFont(font, wordFont);
}
void update(int x, int y) {

  if (overButton(525, 250, width/4, button1Height)) {
    button1Over = true;
  } 
  else {
    button1Over = false;
  }
  if (overButton(462, height/6, 135, button2Height)) {
    button2Over = true;
  } 
  else {
    button2Over = false;
  }
  //
  if (overButton(381, 250, 130, button3Height)) {
    button3Over = true;
  } 
  else {
    button3Over = false;
  }
}

void mousePressed() {

  if (button1Over) {
    println("Button1 pressed");

    myPort.write('A');
    fill(buttonPressed);
    rect(width/1.52, height/2.4, width/6, button1Height);
  }
  if (button2Over) {
    println("Controllo motore");
    if (statomot == 0)
    {
      myPort.write('C');
      statomot=1;
    }
    else if (statomot == 1)
    {
      myPort.write('D');
      statomot=0;
    }

    fill(buttonPressed);
    rect(465, height/5.8, 130, button2Height);
  }
  if (button3Over) {
    println("Button3 pressed");
    myPort.write('B');
    fill(buttonPressed);
    rect(381, 250, 130, button3Height);
  }
}

boolean overButton(int x, int y, int width, int height) {

  if (mouseX >= x && mouseX <= x+width && mouseY >= y && mouseY <= y+height) {
    return true;
  } 
  else {
    return false;
  }
}
void serialEvent(Serial p) 
{ inString = (p.readString()); 
  // println("prova"+inString);  per debug
}

void InfoDati()   // traduce i dati ricevuti, è critica perchè bisogna essere sicuri di ricevere esattamente 6 valori terminati da ,
{ int sensors[] = int(split(inString, ',')); 
  primazona=sensors[0]; 
  secondazona=sensors[1]; 
  terzazona=sensors[2]; 
  numgiri=sensors[4]; 
  statomotore=sensors[5]; 
  float sensorss[] = float(split(inString, ',')); 
  velocita=sensorss[3];
  inString=null; 
}

Anche se commento myPort.bufferUntil(lf); comunque non funziona

void serialEvent(Serial p) 
{ inString = (p.readString()); 
  println("prova"+inString);  // per debug
}

questa scatta solo se spedisci 20 caratteri; hai messo buffer a 20.
Puoi provare a mettere 12 nella buffer() e da Arduino fregartene dei valori e spedire una brutale Serial.print("1,2,3,4,5,6,"); ovvero solo 12 caratteri giusti-giusti ?

In allegato c'è il risultato di quello che mi hai detto di fare.Da errore e si freza l'interfaccia se provo a cliccare un pulsante

Da me funziona, mi sembra.
Ti allego una immagine. I font non avevo i tuoi e ho messo tutto Arial

prova.zip (1.46 KB)

mi incolli il codice che hai usato?

Ecco lo zip con codice e font.

A questo indirizzo c'e' un buon esempio di come leggere ed usare i dati da seriale con Processing usando la serialEvent.
Purtroppo in inglese e non serve a fare "esattamente" quello che vuoi tu.
Quel discorso del buffer(12) e spedire esattamente 12 char è una forzatura per veder muovere l'interfaccia.
Poi di certo scritto così il programma è una cacca. Mica puoi sapere se spedirai sempre 12 char (6 cifre+6 virgole)

prova.zip (1.46 KB)

controlla bene.Il zip contiene uno sketch diverso

Ora dovrebbe essere il file giusto.

Per far funzionare il progetto meglio, porta queste variazioni:

Nel setup:

 myPort = new Serial(this, Serial.list()[0], 9600); 
 myPort.clear();
 //myPort.buffer(12); 
 myPort.bufferUntil('#');  // carattere #  ovvero fine trasmissione

Ora potrai spedire quanti caratteri vuoi basta che fai terminare i dati da # (oppure puoi scegliere tu)
esempio: 1,2,333,4,5,6,#

Naturalmente il programma su Arduino dovrà spedire come ultima cosa il #

forum.zip (40.6 KB)

Un'altra cosa. A te non funziona (credo) perchè nel programma Arduino NON spedisci l'ultima virgola

  ...
   Serial.print(","); 
   Serial.print(reedCounter); 
   Serial.print(","); 
   Serial.println(currentmotstate);

Devi per forza metterla e a questo punto metti anche il #

  ...
   Serial.print(","); 
   Serial.print(reedCounter); 
   Serial.print(","); 
   Serial.print(currentmotstate); 
   Serial.print(","); 
   Serial.print("#");  //fine trasmissione

P.S. forse dopo l'ultima modifica, utilizzo # invece di buffer(12), non serve più ultima virgola

Stupendo!!!Funziona.Ti ringrazio tantissimo davvero