Go Down

Topic: Comunicazione seriale con arduino [aiuto] (Read 2049 times) previous topic - next topic

toti94

Jun 29, 2013, 10:58 pm Last Edit: Jun 30, 2013, 11:25 pm by leo72 Reason: 1
Ragazzi non riesco a trovare un modo efficiente per comandare arduino tramite php.
In pratica dal sito in php gli mando una stringa contenente 2 informazioni, ovvero, il numero della funzione da eseguire e il tempo di delay.
Ora in php io scrivo
Code: [Select]

$serial->senmessage($messaggio);

E ok
ma su arduino non so proprio come gestirmi questa stringa.
Ho provato a usare toInt() per genereare un int per il numero della funzione, ma non va
Ho provato a leggere la stringa in un array così da poter gestirmi l'array e non la stringa ma mi sa di aver sbalgiato :\
Code: [Select]
if(Serial.available()>0)
 {
    for(z=0;z<5;z++)
    {
       stringa[z]=Serial.read();
    }
 }


Qualcuno di voi conosce un metodo migliore e che funzioni? >_< martedì devo portare sto lavoro per l'esame, mi manca solo questo pezzo della comunicazione :\
In pratica mi serve saper prendere il numero della funzione e la pausa da quella stringa :|

nid69ita

Serve sapere cosa contiene $messaggio, un esempio del tipico valore che spedisci.
C'e' un separatore tra i due valori? Mandi un carattere alla fine per sapere che il msg è finito?
my name is IGOR, not AIGOR

toti94

Io ho pensato di inviare la stringa "1200"
Dove il primo carattere è sempre il numero della funzione e dal 2° in poi iniziano i millisecondi della pausa

nid69ita

#3
Jun 29, 2013, 11:44 pm Last Edit: Jun 29, 2013, 11:49 pm by nid69ita Reason: 1
Sarebbe meglio avere un fine messaggio, ad esempio il carattere ascii 13 o andata a capo.
Può esserti utile il comando Serial.ReadBytesUntil()
http://arduino.cc/en/Serial/ReadBytesUntil

Se guardi questo comando potrebbe essere utile, ParseInt() della Serial, ma i due numeri devono essere separati.
http://arduino.cc/en/Serial/ParseInt
my name is IGOR, not AIGOR

toti94

si col php posso inviare ciò che voglio xD
posso anche inviare la stringa "1 200(carattere di fine)"
il problema non sta nell'inviare la stringa, ma nel riceverla e gestirla con arduino

nid69ita

Il cosa inviare è importante perchè in questa maniera stabilisci un "protocollo" di comunicazione e non mandi dati a "casaccio" ma stabilisci delle regole ben precise, visto che poi da lato Arduino i comandi non sono molto sofisticati.
my name is IGOR, not AIGOR

toti94

sisi quello che intendevo dire è che il protocollo ancora non l'ho stabilito e che vorrei stabilirlo in modo da rendere il compito ad arduino il più semplice possibile.
Ma non so quale sia questo modo

toti94

Mi potresti aiutare a trovare il modo giusto per la gestione in arduino? ti ripeto la stringa la posso inviare come vuoi, quindi se tu magari sai come fare questa cosa, dimmi di quale stringa hai bisogno in input per farlo

nid69ita

Io mi baserei sulla readBytesUntil()
http://arduino.cc/en/Serial/ReadBytesUntil

Spedisci 4 cifre più un fine msg ad esempio #
tra le variabili globali:
Code: [Select]

char buf[10];

Code: [Select]

if(Serial.available()>0)
{ byte nletti,funz=0,tempo=0;
  nletti=Serial.readBytesUntil('#', buf, sizeof(buf));
  if(nletti>0)    // può non leggere nulla, se attende oltre timeout
  {  funz=buf[0]-'0';           // primo char convertito in cifra    es. '3' => 51   51-'0'  => 51-48 => 3 come valore
     tempo=(buf[1]-'0')*10+(buf[2]-'0');     
  }
 
}


Non ho arduino collegato, non posso provarlo e stò per andare a dormire   :smiley-sleep:
my name is IGOR, not AIGOR

toti94

Wow grazie mille :)
L'unica cosa che non ho capito bene è  perchè dichiari funzione e tempo come byte?
Code: [Select]
funz=buf[0]-'0';           // primo char convertito in cifra    es. '3' => 51   51-'0'  => 51-48 => 3 come valore
     tempo=(buf[1]-'0')*10+(buf[2]-'0');

Questi due calcoli neanche ho capito :\

Però magari mi rispondi domani xD
Buona notte e grazie mille :D

lesto

vedi, i dati puoi inviarli grezzi, come byte, facilmente leggibili dai PC, o in forma di lettere, facilmente leggibili dagli umani.

Arduino ua l'ascii come tabella per trasformare i caratteri in numeri. Ogni carattere (e i numeri sono caratteri) è trasformato nell'equivalente numero della tabella e poi inviato.
Svataggio: ogni carattere è un byte, quindi mooolta byte/s sono sprecati, oltre che la conversione da lettera a valore utilizzabile (esempio: gli int sono sempre 2 byte grezzi, in lettere dipende da quante cifre ha il numero...)
Vantaggio: se apri il serial monito leggi il numero e non un serie di simboli "a caso"
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

nid69ita

#11
Jun 30, 2013, 10:30 am Last Edit: Jun 30, 2013, 11:05 am by nid69ita Reason: 1
Byte perchè tu invii due valori, la prima è una sola cifra perciò 0-9 e un byte basta  e lo metto in variabile funz (potevo chiamarla pippo)
la seconda 00-99 e perciò un byte basta (messo in variabile tempo, secondo le tue indicazioni iniziali)

Poi ho visto oggi che la seconda è a tre cifre perciò tempo deve essere int.

quando spedisci 1230# allora dopo la lettura avrai nel buffer  di nome buf[]
Code: [Select]

buf
[0] = '1'       carattere '1' che nella tabella ascii è il numero 49
[1] = '2'       carattere '2' in ascii 50
[2] = '3'       carattere '3' in ascii 51
[3] = '0'       carattere '0' in ascii 48
[4] = boh da qui in poi non si sa, ci può essere 0 (valore) o un valore a caso

Per il computer '0' è il valore 48 che stampato a video è il simbolo '0'

Perciò        
funz   =  buf[0] - '0';         ovvero 49-48
tempo=  (buf[1]-'0')*100 + (buf[2]-'0')*10 + (buf[3]-'0') * 1;    ovvero (50-48)*100 + (51-48)*10 + 48-48*1

E' obbligatorio che vengano inviati sempre 4 cifre e a finire il #
altrimenti quel calcolo sballa.  Perciò "010" o "003" e non "10" o "3"
Se il secondo valore non ha dimensione fissa (3 char) allora bisogna usare altra tecnica.

isdigit() è una funzione che ti dice se il carattere è una cifra cioè tra '0' e '9' (tra 48 e 57)
if( isdigit(buf[0]) )   // se la cella 0 di buf contiene una cifra

atoi() converte da stringa a intero (stringa=array o vettori di caratteri con alla fine '\0' o null, NON oggetto String)
val = atoi(buf);    // ma buf deve terminare con carattere '\0'
my name is IGOR, not AIGOR

toti94

ok ora funzione se lo comando tramite monitor seriale
ma non tramite php
quindi il problema sta nel php :\
comunque il codice è questo
Code: [Select]
void loop ()
{
  if(Serial.available()>0)
{ byte nletti,funz=0,tempo=0;
  nletti=Serial.readBytesUntil('#', buf, sizeof(buf));
  if(nletti>0)    // può non leggere nulla, se attende oltre timeout
  {  funz=buf[0]-'0';           // primo char convertito in cifra    es. '3' => 51   51-'0'  => 51-48 => 3 come valore
     tempo=(buf[1]-'0')*100+(buf[2]-'0')*10+(buf[3]-'0');
     pausa= int(tempo);
     funzione= int(funz);
  }
}
switch (funzione)
     {
        case 0:;break;
        case 1: uno_alla_volta(pausa);azzera();break;
        case 2: livelli(pausa);azzera();break;
        case 3: colonne(pausa);azzera();break;
        case 4: verticale(pausa);azzera();break;
     }
}

Però se gli invio una nuova serie, aspetta prima la fine della funzione e poi fa partire l'altra, perchè? :\ non c'è un modo per arrestare l'esecuzione e far partire la nuova?
Inoltre ogni volta che finisce la funzione, aspetta un  po' prima di farla ripartire, non si coporta come si dovrebbe comportare semplicemente in loop (accade con tutte le funzioni)

toti94

#13
Jun 30, 2013, 11:19 pm Last Edit: Jun 30, 2013, 11:23 pm by toti94 Reason: 1
Qual'è il problema di questo pezzo di codice? O.o
Code: [Select]
echo '
<form action="arduino.php" method="post" target="_self">
<label><b>Scegli la funzione </b>
<select name="funzione" size="1">
<option value="1">Uno alla volta</option>
<option value="2">Livelli</option>
<option value="3">Colonne</option>
<option value="4">Verticale</option>
</select></label><br />
<label>Tempo intermittenza in millisecondi (3 cifre) <input type="text" name="pausa" size="4"/></label>
<input type="text" name="nascosto" value="inviato" hidden/>
<input type="submit" value="Invia" />
</form><br />';
if (!isset($_POST['nascosto']))
{}
else
{
if($_POST['pausa']!='' )
{
if (strlen($_POST['pausa'])==3)
{
$messaggio=''.$_POST['funzione'].$_POST['pausa'].'#';
$serial->sendMessage($messaggio,1);
echo $messaggio;
}
else
{
echo'<font color="red">La pausa deve essere formata da 3 cifre</font> <br />';
}
}
else
{
echo'<font color="red">Inserisci la pausa prima di inviare!</font><br />';
}
}


Cioè inviando la stessa stringa ad arduino tramite monitor seriale, arduino funziona.
Però inviandola tramite php, non va :|
Eppure me la stampa la stringa, quindi vuol dire che il messaggio dovrebbe inviarlo.
Inoltre se arduino è in funzione, quando chiudo il monitor seriale e carico la pagina di arduino, questo smette di funzionare :\

Sto utilizzando la php_serial_class

leo72

@toti94:
1) se hai URGENZA, rivolgiti ad un programmatore professionista, gli paghi la parcella e ti fai fare il programma che ti serve. Ho tolto "URGENTE" dal titolo perché il forum non è un centro assistenza
2) perché aprire 2 thread per lo stesso problema? stai avendo problemi nella comunicazione seriale/php tra arduino e computer, perché non continuare qui?

Go Up