seriale e php serial class

salve a tutti, ho ripreso l'esempio in rete per controllare da php un arduino collegato alla seriale.
dopo un pò di peripezie,(installazione ubuntu, apache,e php5, e permessi vari per accedere a dialout) "funziona nel senso che dalla pagina php ho 2 bottoni che inviano 2 caratteri a arduino, che li riceve e fa quello che deve fare.
il problema è che ogni volta che premo uno dei 2 bottoni si riavvia arduino.

<?php error_reporting(E_ALL); ini_set("display_errors", 1); define("PORT","/dev/ttyACM0"); if (isset($_GET['action'])) { include "/usr/share/php5/php_serial.class.php"; $serial = new phpSerial; $serial->deviceSet(PORT); $serial->confBaudRate(9600); $serial->confParity("none"); $serial->confCharacterLength(8); $serial->confStopBits(1); $serial->confFlowControl("none"); $serial->deviceOpen(); sleep(2); if ($_GET['action'] == "on") { $serial->sendMessage("1"); } else if ($_GET['action'] == "off") { $serial->sendMessage("2"); } $read = $serial->readPort(); echo $read; $serial->deviceClose(); } ?> Test Arduino

Test Arduino

<a href="<?=$_SERVER['PHP_SELF'] . "?action=on" ?>">
<button style="width:100px"">

ON


<a href="<?=$_SERVER['PHP_SELF'] . "?action=off" ?>">
<button style="width:100px"">

OFF

ho provato come diceva un utente a mettere sleep(1); ma niente arduino si resetta sempre.
forse è anche normale visto che nel codice php ogni volta che premo uno dei 2 bottoni ho l'apertura della seriale...come risolvere?

Ciao, il problema è che continui ad aprire e chiudere la seriale e mandi l'arduino in reset.
Metti una resistenza da 120Ohm fra +5 e Reset per disabilitare il reset automatico.
http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection

Ricordo ai posteri che lo script sopra citato mi sembra NON FUNZIONI SU WINDOWS.

in teoria basta coambiare la riga define("PORT","/dev/ttyACM0");

Ciao, su phpclasses dicevano che in ambiente windows ci sono dei problemi in lettura o scrittura, adesso non mi ricordo bene quale dei due

allora ho provato con la resistenza tra +5 e reset da 120 ohm ma niente si resetta sempre ogni volta che invio il comando con php.
ho provato anche con il condensatore da 10 uF
http://wp.yellowkazoo.com/?p=177
http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection

entrambi le soluzioni non hanno funzionato .
come posso risolvere?

up
adesso con il condensatore va tutto ok.
grazie!!!

codice pagina php

<?php

error_reporting(E_ALL);
ini_set("display_errors", 1);
define("PORT","/dev/ttyACM0");
 
if (isset($_GET['action'])) {
        include "/usr/share/php5/php_serial.class.php";
    $serial = new phpSerial;
    $serial->deviceSet(PORT);
        $serial->confBaudRate(9600);
        $serial->confParity("none");
        $serial->confCharacterLength(8);
        $serial->confStopBits(1);
        $serial->confFlowControl("none");
       $serial->deviceOpen();
sleep(2);
      switch  ($_GET['action'])  {
      case "1"  :
          $serial->sendMessage("1");
    break;
      case "2"  :
          $serial->sendMessage("2");
    break;
      case "3"  :
          $serial->sendMessage("3");
    break;
      case "4"  :
          $serial->sendMessage("4");
    break;
      case "5"  :
          $serial->sendMessage("5");
    break;
      case "6"  :
          $serial->sendMessage("6");
    break;
      case "a"  :
          $serial->sendMessage("a");
    break;
      case "b"  :
          $serial->sendMessage("b");
    break;
      case "c"  :
          $serial->sendMessage("c");
    break;
      case "d"  :
          $serial->sendMessage("d");
    break;
      case "e"  :
          $serial->sendMessage("e");
    break;
      case "f"  :
          $serial->sendMessage("f");
    break;
}
  $read = $serial->readPort();

    echo $read;

       $serial->deviceClose();
}
 
?>
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Test Arduino</title>
</head>
<body>


<h1>Test Arduino</h1>
 
<a href="<?=$_SERVER['PHP_SELF'] . "?action=1" ?>">
<button style="width:100px""><h1>ON1</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=2" ?>">
<button style="width:100px""><h1>ON2</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=3" ?>">
<button style="width:100px""><h1>ON3</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=4" ?>">
<button style="width:100px""><h1>ON4</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=5" ?>">
<button style="width:100px""><h1>ON5</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=6" ?>">
<button style="width:100px""><h1>ON6</h1></button></a>

<a href="<?=$_SERVER['PHP_SELF'] . "?action=a" ?>">
<button style="width:100px""><h1>OFF1</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=b" ?>">
<button style="width:100px""><h1>OFF2</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=c" ?>">
<button style="width:100px""><h1>OFF3</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=d" ?>">
<button style="width:100px""><h1>OFF4</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=e" ?>">
<button style="width:100px""><h1>OFF5</h1></button></a>
<a href="<?=$_SERVER['PHP_SELF'] . "?action=f" ?>">
<button style="width:100px""><h1>OFF6</h1></button></a>
</body>
</html>

questo è il codice arduino

#define luce1 11  
#define luce2 10
#define luce3 9
#define luce4 8
#define luce5 6
#define luce6 7
byte rx = 0;    // variabile per contenere il carattere ricevuto
int stato1=0;
int stato2=0;
int stato3=0;
int stato4=0;
int stato5=0;
int stato6=0;
long previousMillis = 0; 
long interval = 5000;

void setup()
	{
	Serial.begin(9600); 
        pinMode(luce1, OUTPUT); 
	pinMode(luce2, OUTPUT); 
	pinMode(luce3, OUTPUT); 
	pinMode(luce4, OUTPUT); 
	pinMode(luce5, OUTPUT); 
	pinMode(luce6, OUTPUT); 
        Serial.flush(); 
	}

void loop()
	{

	if (Serial.available() >0)
		{
		rx = Serial.read();
		Serial.flush(); 
   switch (rx) {
  case '1':  
    digitalWrite(luce1,HIGH);
    Serial.println("luce1 accesa");
   
    break;
  case '2':    
    digitalWrite(luce2,HIGH);
    Serial.println("luce2 accesa");
   
    break;
  case '3':    
    digitalWrite(luce3,HIGH);
    Serial.println("luce3 accesa");
   
    break;
  case '4':   
    digitalWrite(luce4,HIGH);
    Serial.println("luce4 accesa");
   
    break;
  case '5':   
    digitalWrite(luce5,HIGH);
    Serial.println("luce5 accesa");
   
    break;
  case '6':    
    digitalWrite(luce6,HIGH);
    Serial.println("luce6 accesa");
  
    break;
    
  case 'a':   
    digitalWrite(luce1,LOW);
    Serial.println("luce 1 spenta");
   
    break;
  case 'b':    
    digitalWrite(luce2,LOW);
    Serial.println("luce 2 spenta");
   
    break;
  case 'c':    
    digitalWrite(luce3,LOW);
    Serial.println("luce 3 spenta");
   
    break;
  case 'd':    
    digitalWrite(luce4,LOW);
    Serial.println("luce 4 spenta");
 
    break;
  case 'e':   
    digitalWrite(luce5,LOW);
    Serial.println("luce 5 spenta");
 
    break;
  case 'f':    
    digitalWrite(luce6,LOW);
    Serial.println("luce 6 spenta");
 
    break;
  
    case '0':
   stato1= digitalRead(luce1);
   if (stato1==1){
      Serial.println("luce1 accesa");
  
 }
      else{
      Serial.println("luce1 spenta");
    }
         stato2= digitalRead(luce2);
   if (stato2==1){
      Serial.println("luce2 accesa");
 
 }
      else{
      Serial.println("luce2 spenta");
  
    }
         stato3= digitalRead(luce3);
   if (stato3==1){
      Serial.println("luce3 accesa");
  
 }
      else{
      Serial.println("luce3 spenta");
 
    }
         stato4= digitalRead(luce4);
   if (stato4==1){
      Serial.println("luce4 accesa");
 
 }
      else{
      Serial.println("luce4 spenta");

    }
         stato5= digitalRead(luce5);
   if (stato5==1){
      Serial.println("luce5 accesa");

 }
      else{
      Serial.println("luce5 spenta");
 
    }
         stato6= digitalRead(luce6);
   if (stato6==1){
      Serial.println("luce6 accesa");

 }
      else{
      Serial.println("luce6 spenta");
  
    }
  } 

   }
     unsigned long currentMillis = millis();
     if(currentMillis - previousMillis > interval) {
    
     previousMillis = currentMillis;
     stato6^=1;
     digitalWrite(luce6, stato6);
  }
}

questo è il problema:
agendo da monitor seriale (sia qllo dell ide sia uno scaricato x ubuntu)
qnd premo uno dei tasti arduino esegue qllo ke deve eseguire e mi da la risposta a qll evento sulla seriale.
agendo dalla pagina php qnd premo uno dei bottoni non sempre esegue il comando e la risposta a volte la stampa a volte no e non sempre pulisce lo schermo dalle stampe precendeti.

leggi senza controllare che effettivamente ti sia arrivato qualcosa. Il pc ha un buffer gigante, però non dai tempo all'arduino di rispondere, senza contare che il pc non è realmente real time e quindi ci possono essere lag anche consistenti.

qualcosa mi dice che in php la readPort(), come la read() di arduino, ritorni -1 se non c'è nulla da leggere.
La soluzione ideale secondo me è di fare un loop che dura al massimo 1 secondo in cui vedi se c'è qualche dato. Se c'è lo leggi e fine, se non c'è dopo un secondo vai in time-out e esci lo stesso dal cislo con un errore

x lesto:
mi spieghi meglio ..?

x ora invece di scrivere sulla seriale dopo aver eseguito il comando

  case '1':  
    digitalWrite(luce1,HIGH);
    Serial.println("luce1 accesa");

faccio eseguire il comando senza scrivere sulla seriale, e sembra andare bene...nel senso che i comandi vengono sempre eseguiti.
mi spiegate meglio la storia del buffer? e visto che devo passare a ide 1 non userò piu serial.flush...
grazie

allora sulla seriale viaggiano al massimo baudrate/10 carattewrei al secondo. Quindi è mooolto lenta, se tu scrive e ti aspetti subito una risposta, può succedere che essa non sia stata ancora spedita! Non solo, ma lato PC può capitare che il messaggio finisca nella seriale HW, che lancoia un interrupt rilavato dal SO, che lo rilancia alla java visrtal maschine, che lo rilancia alla libreria, che rileva che c'è un carattere. nel frattempo tutto questo sistema potrebbe essere messo in pausa per eseguire altre cose in altri thread/processi, in uno scema più o meno complicato. certo parliamo di millisecondi, ma abbastanza per credere che non sia arrivata nessuna risposta.

Insomma è come se appena uno ti risponde al telefono gli dici "ciaocomestai?" e poi metti giù. E' raro che lui faccia in tempo a risponderti, però alla volte succede.

Oh, poi non ho letto il tuo codice ma gli ho dato uno sguardo veloce,magari ci sono altri errori

Quindi come dovrei risolvere? X adesso mando un carattere alla volta e ce la fa a risp in tempo, anzi la risp l ho eliminata e cosi esegue sempre il comando.

non leggere subito la risposta ma metti un delay fisso (soluzione facilissima)

continua a leggere fichè non arriva un carattere o non superi un certo tempo, detto time-out (soluzione facile)

lesto:
non leggere subito la risposta ma metti un delay fisso (soluzione facilissima)

continua a leggere fichè non arriva un carattere o non superi un certo tempo, detto time-out (soluzione facile)

Vorrei usare la soluzione del time out, ma vorrei capire dove e come usarlo.
Nn voglio il codice fatto ma capire il principio.
Grazie lesto

timeout = 1000;
manda messaggio;
inizio = millis();
do{
risp = leggi risposta
}finchè ris == -1 and millis()-inizio < timeout

se ris == -1{
errore nessuna risposta in tempo utile
}else{
la risposta è ris
}

edit: noto che il tuo problema è anche sull'invio, e mi sembra molto strano. Forse devi dare una flush lato PHP prima di chiudere la connessione seriale, anche se mi sembra starno che non lo faccia di già con la close.. oppure se ti basi sul fatto che il comando sia stato esegiuito solo dalla risposta senza un riscontro visivo allora è per il motivo di cui sopra, e spiega come mai con una modifica del codice arduino tutto sebra funzionare (non verifichi più il successo dalla risposta seriale ma visualmente)

allora cerco un pò di studiare la spiegazione ke mi hai scritto....ti spiego come funziona adesso:
dalla pagina php tramite un bottone invio un carattere alla seriale, arduino che nel suo loop è sempre in ascolto sulla seriale qnd riceve ql carattere mi accende un led (ed effettivamente adesso lo fa) solo ke io lato php cioè nella pagina web non so se il comandop è andato a buon fine , posso saperlo solo se ho il led davanti. se voglio ricevere la conferma dell accensione tramite serilae nascono quei problemi strani.

lesto:
timeout = 1000;
manda messaggio;
inizio = millis();
do{
risp = leggi risposta
}finchè ris == -1 and millis()-inizio < timeout

se ris == -1{
errore nessuna risposta in tempo utile
}else{
la risposta è ris
}

edit: noto che il tuo problema è anche sull'invio, e mi sembra molto strano. Forse devi dare una flush lato PHP prima di chiudere la connessione seriale, anche se mi sembra starno che non lo faccia di già con la close.. oppure se ti basi sul fatto che il comando sia stato esegiuito solo dalla risposta senza un riscontro visivo allora è per il motivo di cui sopra, e spiega come mai con una modifica del codice arduino tutto sebra funzionare (non verifichi più il successo dalla risposta seriale ma visualmente)

lesto scusami, ma non riesco a capire cosa a qst codice, dove dovrei usarlo...
scusami,

è il codice lato PHP, come vedi attende una risposta per 1000 millisecondi (1 secondo), prima di mostrare un messaggio di errore. Se la risposta arriva prima di un secondo, non resti in attesa inutilmente ma mostri subito il messaggio di successo.

quindi devo usare qst funzione qnd invio il dato via php...ma millis() nn è una funzione di arduino? c'è ank in php?

io hgo scritto millis() per far capire, probabilmente c'è l'equivalente per php