Comandare arduino in php

eseguito via shell non fornisce nessun output nel senso che esegue il comando tanto é vero che confrollando i parametri con stty -a -F /dev/ttyACM0 risulta tra le varie cose "-hupcl" che dovrebbe corrispondere alla disabilitazione del DTR

mi ricordo che la cosa andava bene con arduino 2009 (che purtroppo non ho sotto mano adesso), forse potrebbe essere un problema legato al fatto che le seriali sono diverse in 2009 e arduino uno? infatti collegando la 2009 in linux compare il device /dev/ttyUSB0, in arduino uno diventa /dev/ttyACM0

Il chip FTDI della 2009 è un convertitore USB/seriale mentre l'Atmega8U2 della UNO è un micro programmato per emulare questa cosa via software per cui cambiano le modalità come vengono viste dall'SO.

ti ringrazio molto per la precisazione! a questo punto credo che tutti i vari tutorial in rete relativi a php_serial_class, a proxy come serproxy o ser2net non funzionino più con arduino uno visto che di fatto non esiste più una porta seriale ma una usb vera e propria, mi sbaglio??

Non proprio. L'Arduino non è un host USB ma il firmware dell'Atmega8U2 spedisce un vendor:product USB valido per cui l'Arduino UNO viene identificato dall'SO come USB anche se poi viene gestita come porta seriale (difatti su Win viene visto come una porta COM).

ma allora secondo te perché non funziona con linux? da windows riesco a disabilitare il dtr via software con exec("mode com1: BAUD=9600 PARITY=n DATA=8 STOP=1 to=off dtr=off rts=off"); in php e non ho problemi a comunicare via seriale senza usare né classi particolari né serial proxy in linux non c'é verso di farla andare anche usando ser2net continua a resettarsi

Perché sono 2 SO diversi e probabilmente gestiscono la porta in maniera differente.

@FreeDomotic, potresti spiegarmi bene come hai risolto in php su Windows x comnicare con l'arduino? Grazie!

Ciao ragazzi, la discussione mi ha subito appassionato e stavo provando qualcosa usando easyphp per simulare un server sul mio pc winzoz!
Sono riuscito perfettamente a scrivere sulla porta com3 però ho un grande problema! Non riesco a leggere ciò che mi da in risposta l’arduino!
Utilizzando come negli esempi precedenti “fread($risorsa, fsize($risorsa))”.
Qualche consiglio?

ciao Guglio, allora ho risolto in questo modo usando una funzione per inviare dei caratteri ad arduino in php

<?php
// inizializzazione porta
exec(“mode com1: BAUD=9600 PARITY=n DATA=8 STOP=1 to=off dtr=off rts=off”);
function sendToSerial($messaggio){
$fp =fopen(“com1”, “w”);
fwrite($fp, $messaggio);
fclose($fp);
}
?>

poi nel codice php che gestisce l’invio dei caratteri uso questo

if ($_GET[‘action’] == “d”) {

  • //invia il comando *
  • sendToSerial(“d”);*

ps: non uso easyphp ma server2go

spero ti sia utile…

Sullo scrivere non ci sono problemi, è sul leggere che sto incontrando qualche difficoltà!

Ecco il codice da me realizzato

$VAR = $_GET['testo'];

  //$cmd_str = "MODE COM3 BAUD=9600 PARITY=N DATA=8 STOP=1 TO=ON OCTS=ON ODSR=OFF IDSR=OFF RTS=HS DTR=ON"; 
  //exec($cmd_str);

$porta_seriale = fopen("COM3", "w+");
fwrite($porta_seriale, $VAR);

sleep(2); //Per attendere la risposta dell'arduino

if($risposta = fread($porta_seriale, 30)){
echo "
True
";
echo $risposta;
}
else
{
echo "
False
";
echo $risposta;
}
fclose($porta_seriale);

Così facendo ogni tanto riesco a leggere ciò che mi risponde l'arduino, che presenta il seguente codice:

int Led=13;
int incomingByte;  

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

void loop()
{
  if (Serial.available() > 0) {
    incomingByte = Serial.read();

    if (incomingByte == 'a') {
      digitalWrite(Led, HIGH);
      Serial.println("LED acceso!");
    }
    else if (incomingByte == 'b') {
      digitalWrite(Led, LOW);
      Serial.println("LED spento!");
    } 
    else{
      Serial.print("comando NON riconosciuto: ");
      Serial.println(incomingByte);
    }
  }
}

Prima di poter comunicare con la porta com devo eseguire il comando (IO, dal prompt se no non funziona) "MODE COM3 BAUD=9600 PARITY=N DATA=8 STOP=1 TO=ON OCTS=ON ODSR=OFF IDSR=OFF RTS=HS DTR=ON" ed ogni tanto la porta com scompare, o dice che è utilizzata da qualche altra parte, quando in realtà nessun applicazione accede alla porta.

cosa intendi per

Così facendo ogni tanto riesco a leggere ciò che mi risponde l'arduino, che presenta il seguente codice:

il problema potrebbe essere in sleep(2); //Per attendere la risposta dell'arduino non è detto che arduino impieghi solo 2 millisecondi(?) a rispondere, anzi, la seriale è molto lenta (baud di 9600 = 9.6 caratteri al millisecondo) a cui devi aggiungere il tempo di esecuzione dei vari codici. E' comunque strano perchè il codice arduino è telmente basico che dovrebbe eseguirsi in molto meno di 2ms...

a meno che arduino non stia stampando: Serial.print("comando NON riconosciuto: "); che essendo molto più di 19 caratteri (2 ms), sicuramente non viene ricevuto completamente.

lesto: cosa intendi per

Così facendo ogni tanto riesco a leggere ciò che mi risponde l'arduino, che presenta il seguente codice:

il problema potrebbe essere in sleep(2); //Per attendere la risposta dell'arduino non è detto che arduino impieghi solo 2 millisecondi(?) a rispondere, anzi, la seriale è molto lenta (baud di 9600 = 9.6 caratteri al millisecondo) a cui devi aggiungere il tempo di esecuzione dei vari codici. E' comunque strano perchè il codice arduino è telmente basico che dovrebbe eseguirsi in molto meno di 2ms...

a meno che arduino non stia stampando: Serial.print("comando NON riconosciuto: "); che essendo molto più di 19 caratteri (2 ms), sicuramente non viene ricevuto completamente.

Sono due secondi non due millisecondi (http://php.net/manual/en/function.sleep.php). Il problema non è quello, anzi, sembra che funzioni da quando ho inserito quel codice!

Per il resto, intendo che ci sono volte che mi legge dalla seriale e altre volte, come detto prima, no perchè la porta com scompare!

Up! :)

Xfox: Sono due secondi non due millisecondi (http://php.net/manual/en/function.sleep.php). Il problema non è quello, anzi, sembra che funzioni da quando ho inserito quel codice!

ok, allora senza non aspetti nulla e quindi il problema si presenta nella sua forma peggiore, con 2 secondi ricevi un sacco di dati, ma secondo me la cosa migliore è usare un carattere di fine messaggio (come lo '\0', però mi sa che se lo forzi viene inteso come fine trasmissione seriale, come fare Serial.end(); ) Un'altra soluzione è: lato arduino chiudere e subito riaprie la seriale la seriale, il codice PHP dopo aver svuotato il buffer di dati ricevuti fino a quel momento leggerà il segnale di EOF (proprio come se avessi raggiunto la fine di un file), ma comunque arduino rimarrebbe subito in attesa di un'altra connessione seriale. In pratica setup; attivi seriale loop; stampi su seriale, stoppi la seriale, attivi la seriale

Xfox: Per il resto, intendo che ci sono volte che mi legge dalla seriale e altre volte, come detto prima, no perchè la porta com scompare!

allora, nel mio sistema alla prima connessione la porta impiega qualche secondo per essere rilevata, poi dopo posso attaccare e riattaccare la USB e viene rilevata istantaneamente. Se invece perdi proprio la COM, allora pèuò essere sia un problema driver, che un problema FTDI (o u2qualcosa per l'arduino UNO), che semplicemente una assegnazione di un'altro numero di porta (ma moolto stano, di solito il SO tende ad assegnare sempre la stessa, ovvero la prima disponibile). Sinceramente, vedendo che usi la COM3, dubito che tu abbia 2 seriali sul tuo PC, credo che abbia fatto un pò di casino installando i driver. Cancellali tutti (finchè il numero di COM non è uguale al numero di porte seriali che ha il tuo PC) e poi reinstallali. (porta seriale: http://www.piemontewireless.net/images/2/23/Serial_port_t.jpg)

Io per porta seriale (simulata) intendevo l'USB... E comunque l'arduino è collegato ad uno sdoppiatore USB (che mi fornisce altre 4 uscite) però ovviamente quando attacco l'arduino allo sdoppiatore, nessun'altra periferica è attaccata!

Per il resto non capisco a cosa dovrebbe servirmi stoppare la seriale! Cioè se do il comando Serial.end() l'arduino invia un carattere di fine che viene interpretato dal php come fine del file?

Xfox: Io per porta seriale (simulata) intendevo l'USB... E comunque l'arduino è collegato ad uno sdoppiatore USB (che mi fornisce altre 4 uscite) però ovviamente quando attacco l'arduino allo sdoppiatore, nessun'altra periferica è attaccata!

appunto, viene simulata via driver, e a quanto pare, se stai usando com3, il pc vede altre 2 porte com (simulate o no poco importa). Se sono 2 porte fisiche ok, altrimenti hai fatto casino installando i drivers. Prova anche a non usare l'hub usb, potrebbe essere quello il problema (anche con nulla attaccato)

Xfox: Per il resto non capisco a cosa dovrebbe servirmi stoppare la seriale! Cioè se do il comando Serial.end() l'arduino invia un carattere di fine che viene interpretato dal php come fine del file?

esatto! Quindi tu fai una read finchè non rilevi fine del file... così non sprrechi secondi preziosi :D

Digitando il comando "mode" sul prompt di comando mi vede solamente utilizzate COM1 (credo sia la porta seriale sul retro del pc) e la COM3 (che è l'arduino, che ho anche spostato dall'hub). Ho disinstallato e reinstallato i driver e gli è stata assegnata nuovamente la COM3.

Ecco codice php:

$VAR = $_GET['testo'];

  //$cmd_str = "MODE COM3 BAUD=9600 PARITY=N DATA=8 STOP=1 TO=ON OCTS=ON ODSR=OFF IDSR=OFF RTS=HS DTR=ON"; 
  //exec($cmd_str);

$porta_seriale = fopen("COM3", "w+");
fwrite($porta_seriale, $VAR);

sleep(2);

if($risposta = fread($porta_seriale, 30)){
echo "
True
";
echo $risposta;
}
else
{
echo "
False
";
echo $risposta;
}

fclose($porta_seriale);

Ed ecco il codice arduino:

int Led=13; int incomingByte;

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

void loop() { if (Serial.available() > 0) { incomingByte = Serial.read();

if (incomingByte == 'a') { digitalWrite(Led, HIGH); Serial.println("LED acceso!"); } else if (incomingByte == 'b') { digitalWrite(Led, LOW); Serial.println("LED spento!"); } else{ Serial.print("comando NON riconosciuto: "); Serial.println(incomingByte); } } delay(500); Serial.end(); delay(500); Serial.begin(9600); }

Ho collegato l'arduino e ho avviato la pagina index.php?testo=a, ovvero il comando per accendere il led (Senza aver eseguito la parte di codice che configura la porta COM3, ovvero "//$cmd_str = "MODE COM3 BAUD=9600 PARITY=N DATA=8 STOP=1 TO=ON OCTS=ON ODSR=OFF IDSR=OFF RTS=HS DTR=ON"; //exec($cmd_str);", la porta com è scomparsa! Ho provato a staccare e riattaccare l'arduino ma ancora non compare! Credo compaia dopo che riavvio il sistema! [/quote]

Se invece eseguo la riga per configurare la porta com (la eseguo manualmente dal prompt) ed invio la lettera "a", il led fa un paio di lampeggi velocissimi e la porta com scompare, la pagina php non finisce di caricare così aggiorno e stavolta carica subito però dandomi dei warning:

Warning: fopen(COM3) [function.fopen]: failed to open stream: Permission denied in C:\Program Files\EasyPHP-5.3.6.0\www\arduino\index.php on line 8

Warning: fwrite() expects parameter 1 to be resource, boolean given in C:\Program Files\EasyPHP-5.3.6.0\www\arduino\index.php on line 9

Warning: fread() expects parameter 1 to be resource, boolean given in C:\Program Files\EasyPHP-5.3.6.0\www\arduino\index.php on line 14

False

Warning: fclose() expects parameter 1 to be resource, boolean given in C:\Program Files\EasyPHP-5.3.6.0\www\arduino\index.php on line 26

che sistema operativo usate? linux è ben ristretto sui permessi, dovete dare all'utente www-data i permessi della seriale, va fatto da shell ma non ricordo i comandi

superlol: che sistema operativo usate? linux è ben ristretto sui permessi, dovete dare all'utente www-data i permessi della seriale, va fatto da shell ma non ricordo i comandi

Windows 7, ma credo che non sia del tutto corretto quello che dici, perchè per scrivere è semplice, il problema è leggere!

secondo me (ma non ho mai provato queste cose e non ho il tempo per provarle attualmente) il problema è che bisogna avere il tempismo corretto.

intendo:

$VAR = $_GET['testo'];

  //$cmd_str = "MODE COM3 BAUD=9600 PARITY=N DATA=8 STOP=1 TO=ON OCTS=ON ODSR=OFF IDSR=OFF RTS=HS DTR=ON"; 
  //exec($cmd_str);

$porta_seriale = fopen("COM3", "w+");
fwrite($porta_seriale, $VAR);

while(!fread($porta_seriale, 30));

if($risposta = fread($porta_seriale, 30)){
echo "
True
";
echo $risposta;
}
else
{
echo "
False
";
echo $risposta;
}

fclose($porta_seriale);

ma bisogna mettere un ignore user abort in cima e un set time limit a 0 (bisogna che il safe mode in php.ini sia off..)

poi non so con win 7, ad ogni modo i permessi sulla seriale in linux sono sicuro in quanto www-data non ha accesso a niente

ripeto che non ho provato ma mi pare ragionevole così...

inoltre non so come si comporta PHP con uno streaming dati, per queste cose bisognerebbe usare PHP con ajax o flash