Go Down

Topic: controllo remoto di un robot dal computer? (Read 28510 times) previous topic - next topic

igor99480

ciao,
mi spieghi questa riga? while(Serial.available()==0){}
che senso ha lasciar scriverla e non mettere niente dentro come si dovrebbe fare?
in realtò si scrive if(Serial.availale()>0){codice}
prova a usare questo sketch
Code: [Select]

void setup() 
{
delay(2000); //mettilo sempre prima di ogni Serial.begin();
Serial.begin(115200);
pinMode(13,OUTPUT);
}

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

if(er=='3')
    digitalWrite(13,HIGH);
else
    digitalWrite(13,LOW);   

Serial.write(er); //sicuro che è write e non print/ln?
Serial.write(10);
}
}

lestofante

significa che finchè la condizione è vera il micro resta bloccaro nel while, in pratica è un modo per aspettare che arrivino i dati su seriale. Bruttissimo appoccio, ma funzionale
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

igor99480


significa che finchè la condizione è vera il micro resta bloccaro nel while, in pratica è un modo per aspettare che arrivino i dati su seriale. Bruttissimo appoccio, ma funzionale

in effetti non ho mai visto scritto così.

ah il codice che ho riscritto funziona. alemno da serial monitor dell'ide va.

er_like_no_other


ciao,
mi spieghi questa riga? while(Serial.available()==0){}
che senso ha lasciar scriverla e non mettere niente dentro come si dovrebbe fare?
in realtò si scrive if(Serial.availale()>0){codice}

il problema non è su arduino, quello va e l'ho provato col serial monitor....

poi fare:
Code: [Select]

void loop()
{
if(Serial.availale()>0){codice}
}

e fare:
Code: [Select]

void loop()
{
while(Serial.availale()==0){}
codice
}

secondo me il micro fa le stesse operazioni, l'ho scritto in fretta quel codice e non ho badato molto all' "estetica", ho modificato un codice che avevo già per fare presto e come è venuto è venuto :P
a me interessa capire come gestire la seriale dal visual C#...
Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

igor99480



ciao,
mi spieghi questa riga? while(Serial.available()==0){}
che senso ha lasciar scriverla e non mettere niente dentro come si dovrebbe fare?
in realtò si scrive if(Serial.availale()>0){codice}

il problema non è su arduino, quello va e l'ho provato col serial monitor....

poi fare:
Code: [Select]

void loop()
{
if(Serial.availale()>0){codice}
}

e fare:
Code: [Select]

void loop()
{
while(Serial.availale()==0){}
codice
}

secondo me il micro fa le stesse operazioni, l'ho scritto in fretta quel codice e non ho badato molto all' "estetica", ho modificato un codice che avevo già per fare presto e come è venuto è venuto :P
a me interessa capire come gestire la seriale dal visual C#...


beh scrivere while seriale è disponebile o if seriale è ecc è la stessa cosa ;)

per quanto riguarda il controllo dell seriale da c, io so che normalmente si indica la porta e poi la si apre.il collegamento non deve essere interrotto perchè è solo una perdita  di tempo. purtroppo non uso c# ma basic per fare queste piccole app veloci.
devi vedere un po di documentazioen in rete ;)
Igor

er_like_no_other


per quanto riguarda il controllo dell seriale da c, io so che normalmente si indica la porta e poi la si apre.il collegamento non deve essere interrotto perchè è solo una perdita  di tempo. purtroppo non uso c# ma basic per fare queste piccole app veloci.
devi vedere un po di documentazioen in rete ;)
Igor

ok grazie per le info ;)
purtroppo in internet non ho trovato molto che mi possa aiutare a capire il mio problema, i dati li ricevo ma non capisco cosa succede nel programma e come li interpreta il visual c#...
Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

lestofante


[...]
secondo me il micro fa le stesse operazioni, l'ho scritto in fretta quel codice e non ho badato molto all' "estetica", ho modificato un codice che avevo già per fare presto e come è venuto è venuto :P
a me interessa capire come gestire la seriale dal visual C#...


scritta coì hai ragione, ma se nel loop ci fosse altro (per esempio la lettura di un sensore), nel caso if la lettura avverrebbe velocissimamente, nel secondo caso invece ci sarebbe una lettura SOLO quando arriva almeno un carattere su seriale. Che se poi questo carattere non lo leggi rimane disponibile e torni all'esempio dell'if.

In oltre la combinazione if con dentro il while può essere molto comoda: mettiamo che decidi che le vuoi fare un comando così composoto:
1byte = lettera del comando
2byte = eventuale valore int (1 int = 2 byte) da impostare

come faresti?

fai un if (anzi uno switch) e dici:
se ho ricevuto un comando, e quel comando necessita di un valore, allora cicla la seriale finchè non leggo anche i due byte successivi.

Ora noterai che se per un errore di comunicazione i 2 byte non arrivano mai tutto il programma si blocca.

la soluzione sta nell'usare un buffer dei comandi nell'aggiungere un carattere di fine comando (lo '\n' che è il new-line, ovvero il carattere di a capo per i sistemi unix. per i windows sono 2 caratter '\r' + '\n' (il famoso vbCrLf per chi viene da visual basic et similia) e se non erroro nei mac è '\n' '\r'

a questo punto non usi un while, ma quando arriva un carattere via seriale lo metti nel buffer. quando leggi un \n allora controlli svuoti il buffer ed esegui il comando.

Noterai che in questo caso, anche in caso di errore di comunicazione (dal cavo attaccato male al fulmine a 100 metri) perderai il comando attuale ed eventualmente il successivo, ma il resto continuerà a funzionare egregiamente, specialemte se dai un avviso di errore in caso di comando non riconosciuto o di successo in caso di comando eseguito correttamete, in modo che anche l'altra parte sappia se il tutto è avvenuto correttamente oppure prenda la "decisione" pèiù saggia (potrebbe fregarsene dell'errore, oppure rifare la richiesta o chissà che altro)

come vedi potremmo andare avanti all'infinito, l'unico limite è la fantasia, e la soluzione migliore dipende da cosa vuoi fare. Per un piccolo esercizio il while va più che bene!
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

superlol

allora fai così:
crea una selectbox e cerca online il codice che elenca le seriali, quindi doppio click sul form in generale e metti li il codice in modo che aggiorni la seriale.
fatto questo affianco metti un pulsante "connetti" in tal modo quando lo clicchi apri la seriale selezionata dalla selectbox, sempre qui attivi un pulsante detto disconnetti e blocchi i pulsanti connetti e la selectbox.

ok quindi ora hai per aprire e chiudere la seriale (quindi evita altri check per favore)

ora fai così:
crea una funzione che deve fare quando riceve un dato da seriale e associala all'evento di ricezione così separiamo invio e ricezione (per fortuna).

fatto questo riprendi il tuo codice del solo invio e rimettilo dentro XD

avendo queste possibilità è inutile fasciarsi la testa con possibili timing errati, tanto vale mettere un hadler che gestisce la seriale in ascolto.
con visual basic è anche più facile  :P

tazzo

Vedo che hai scelto Windows Forms...hai impostato la velocità corretta nel controllo SerialPort?
I caratteri con punti interrogativi vuol dire che non sono lettere o caratteri sensati, dovresti capire che byte sono con dei breakpoint nel codice.
La seriale ti consiglio di lasciarla sempre aperta fintanto che comunichi con Arduino, puoi usare gli eventi del controllo SerialPort per semplificarti la vita
La prossima volta allega il progetto, ti aiuto meglio così

Ciao

er_like_no_other


allora fai così:
crea una selectbox e cerca online il codice che elenca le seriali, quindi doppio click sul form in generale e metti li il codice in modo che aggiorni la seriale.
fatto questo affianco metti un pulsante "connetti" in tal modo quando lo clicchi apri la seriale selezionata dalla selectbox, sempre qui attivi un pulsante detto disconnetti e blocchi i pulsanti connetti e la selectbox.

ok quindi ora hai per aprire e chiudere la seriale (quindi evita altri check per favore)

ora fai così:
crea una funzione che deve fare quando riceve un dato da seriale e associala all'evento di ricezione così separiamo invio e ricezione (per fortuna).

fatto questo riprendi il tuo codice del solo invio e rimettilo dentro XD

avendo queste possibilità è inutile fasciarsi la testa con possibili timing errati, tanto vale mettere un hadler che gestisce la seriale in ascolto.

la prima parte ho provato a farla ma non ci sono riuscito :( ho fatto solo un checkbox per aprire e chiudere ma la lista no... comunque ho provato ad associare la lettura all'evento della ricezione dei dati salla porta, questo è il codice:
Code: [Select]
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            string read = serialPort1.ReadExisting();
            label3.Text = read;
        }

però mi da errore e si blocca durante l'esecuzione, e non capisco cosa ci sia di sbagliato :~ allego il progetto su cui sto sperimentando visual C#...
grazie mille a tutti per l'aiuto ;)

comunque qua mi sembra di andare OT, magari dopo guardo se posso chiedere sul forum di visual studio ;)


con visual basic è anche più facile  :P

visual basic non mi piace perchè senza parentesi graffe faccio confusione :P
Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

superlol

#55
Aug 25, 2012, 02:41 pm Last Edit: Aug 25, 2012, 02:42 pm by superlol Reason: 1
cavolo ho installato visual vb, visual c++ ora mi scarico anche visual c#  XD

comunque così a memoria c'era il sistema per ottenere l'array delle porte seriali e con un foreach le portavi come elementi della textbox, comunque fammi dare un'occhiata e ti riallego tutto ;)

tazzo

Visual Basic, C#.. alla fine è Windows Forms.. stessa minestra :)
Io avrei usato WPF per un'interfaccia più accattivante che non sembri un pizzoso gestionale!

superlol

Code: [Select]

            string[] ports = System.IO.Ports.SerialPort.GetPortNames();
            foreach(string port in ports) {
                comboBox1.Items.Add(port);
            }

questo è il codice da inserire al caricamento per elencare le porte nella combobox.

Code: [Select]
string read = serialPort1.ReadLine();
questo è per avere la lettura da seriale da mettere al posto di
Code: [Select]
string read = serialPort1.ReadExisting();

fammi sapere se va (ora però la seriale legge una riga, non di più)

tazzo

#58
Aug 25, 2012, 03:06 pm Last Edit: Aug 25, 2012, 03:20 pm by flz47655 Reason: 1
Ho notato che quando scrivi col write non fai scaricare il buffer sulla porta
Per sicurezza aggiungi:

Code: [Select]
serialPort1.BaseStream.Flush();

Ad ogni modo oggi ho provato il tuo codice e il problema è un altro, diciamo non immediato per un beginner di C#.

Nell'evento serialPort1_DataReceived non puoi accedere al controllo label3 perché sei su un altro thread e quindi l'istruzione

Code: [Select]
label3.Text = read;

non viene eseguita. Ti consiglio di mettere SEMPRE la spunta su tutte le voci nella colonna Thrown del menù Debug/Exceptions per vedere in debug tutti gli errori.

la lettura avviene correttamente, il problema è li, nell'aggiornamento dell'interfaccia!

Come FIX veloce ti posso dire di sostituire con

Code: [Select]

            BeginInvoke(new Action(() => {
              label3.Text = read;
            }));


ma leggi su internet qualcosa a proposito dei thread e dell'accesso ai controlli.

Altro consiglio, non rallentare il programma con progressbar o menate simili se non servono.. più è veloce meglio è! Andava di moda 20 anni fa la progress bar, ora meno c'è meglio è.

Ciao

superlol


Ho notato che quando scrivi col write non fai scaricare il buffer sulla porta
Per sicurezza aggiungi:

Code: [Select]
serialPort1.BaseStream.Flush();

Ad ogni modo oggi ho provato il tuo codice e il problema è un altro, diciamo non immediato per un beginner di C#.

Nell'evento serialPort1_DataReceived non puoi accedere al controllo label3 perché sei su un altro thread e quindi l'istruzione

Code: [Select]
label3.Text = read;

non viene eseguita. Ti consiglio di mettere SEMPRE la spunta su tutte le voci nella colonna Thrown del menù Debug/Exceptions per vedere in debug tutti gli errori.

la lettura avviene correttamente, il problema è li, nell'aggiornamento dell'interfaccia!

Come FIX veloce ti posso dire di sostituire con

Code: [Select]

            BeginInvoke(new Action(() => {
              label3.Text = read;
            }));


ma leggi su internet qualcosa a proposito dei thread e dell'accesso ai controlli.

Altro consiglio, non rallentare il programma con progressbar o menate simili se non servono.. più è veloce meglio è! Andava di moda 20 anni fa la progress bar, ora meno c'è meglio è.

Ciao

sul fatto della barra confermo è noiosa  XD

piuttosto invece non mi pare sia un problema relativo ai thread in quanto il codice è sempre quello, non varia intendo non passi tra listati diversi (che allora si potrebbe dare errore) ma sullo stesso listato..
erro?  :smiley-roll-sweat:

almeno io non ho mai avuto di questi problemi quando lavoravo con il serial receive su vb.net, forse è una cosa più da C#  :smiley-sweat:

Go Up