Autore Topic: [RISOLTO]: Lettura dati provenienti da Arduino mediante porta Seriale  (Letto 9326 volte)

Offline luigitessitore

  • Gamberetto
  • *
  • Post: 6
    • Mostra profilo
Salve a tutti,
premetto che non sono proprio alle primissime armi di programmazione, tuttavia non riesco a venire a capo ad un problema relativo alla lettura di dati dalla porta seriale.
Lo scenario: il mio Arduino mi invia una sequenza di test tramite seriale del tipo: #123456789! dove # e ! sono dei char di start e stop.
Ora, per quanto abbia cercato in lungo e in largo nei forum di mezzo mondo, non riesco a trovare la strada per "estrarre" questo dato pulito.
Naturalmente ho settato l'apposito componente con la velocità di default di Arduino (9600), la porta seriale giusta, etc.
CREDO che il problema nasca dal fatto che il metodo _Read del componente SerialPort viene eseguito in loop fino a quando la porta non viene esplicitamente chiusa. Però non c'è sincronia con Arduino. Pertanto, spesso della stringa leggo solo 3/4 caratteri e shiftati rispetto al pattern che invio.
Il dato "sembra" si possa estrarre se riesco a far accumulare una serie di "loop" su una variabile.. Ottengo qualcosa del tipo "456789!#123456789!#123" e da qui, con un po' di lavoro, si dovrebbe riuscire a pulire la sola parte "numerica".
Veramente questa è l'unica strada, oppure mi sono perso qualcosa?

PS.
Con Arduino posso fare come mi pare.. nel senso che non devo per forza utilizzare la forma che ho individuato; posso anche fare qualcosa del tipo: # \r\n, 1\r\n, etc.

Grazie per l'attenzione.
« Ultima modifica: 28 Dicembre 2012, 23:02:28 da luigitessitore »

Offline fsurfing

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.484
    • Mostra profilo
Re: Lettura porta Seriale.. Help.
« Risposta #1 il: 28 Dicembre 2012, 18:02:47 »
io tempo fa ho fatto dialogare gambas e arduino tramite seriale è non ho avuto problemi ..
purtroppo non trovo più lo sketch ne il codice gambas , però se tu alleghi il tuo , magari si può capire qualcosa.
« Ultima modifica: 28 Dicembre 2012, 18:21:57 da fsurfing »

Offline fsurfing

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.484
    • Mostra profilo
Re: Lettura porta Seriale.. Help.
« Risposta #2 il: 28 Dicembre 2012, 22:48:26 »
con questo codice dovresti ottenere una lettura pulita, dipend ecomunque dal codice che usi nello scema

Codice: gambas [Seleziona]

Public Sub SPort_Read()
  Dim s, $s As String
  Dim i As Integer
  
    Read #Sport, s, Lof(Sport)
    
    s = Replace(s, "\r\n", "")
  
    
  For i = 1 To Len(s)
    $s = Mid(s, i, 1)
    
    If $s = "#" Then
      sbuf = ""
    Else If $s = "!" Then
      textbox1.text = sbuf
    Else
      sbuf &= $s
    Endif
  Next

  

End


sbuf è una variabile di tipo globale

Offline luigitessitore

  • Gamberetto
  • *
  • Post: 6
    • Mostra profilo
Re: Lettura porta Seriale.. Help.
« Risposta #3 il: 28 Dicembre 2012, 22:56:53 »
PERFETTO!
In effetti, avevo fatto una prova settando sbuf come variabile interna alla funzione (con DIM).. ma dopo un secondo il dato appariva illeggibile.
Settandola come PUBLIC rimane fissa.

GRAZIE, sei veramente competente e gentile!
Credo che il tuo contributo possa servire a molte persone.
Ancora Grazie!
« Ultima modifica: 28 Dicembre 2012, 23:01:41 da luigitessitore »

Offline fsurfing

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.484
    • Mostra profilo
Re: Lettura porta Seriale.. Help.
« Risposta #4 il: 28 Dicembre 2012, 23:01:44 »
aggiungi un delay(500)

dopo l' istruzione di invio dati alla seriale nello schema di arduino

io ad esempio ho usato:

Codice: [Seleziona]
Serial.write('#');
          //int sensorValue = analogRead(A0);
          Serial.println( analogRead(A1));
          Serial.write('!');
          delay(1000);

Offline El Berto

  • Grande Gambero
  • ***
  • Post: 150
    • Mostra profilo
Magari riesco a capirci qualcosa anch'io.....

Come si gestisce la lettura della porta seriale?
In pratica, se io con Arduino trasmetto la stringa:

Codice: [Seleziona]
forseperchèdellafatelquietetuseil'immagoamesicaravieniosera.

Nella routine SPortRead ho inserito questo codice:
Codice: [Seleziona]
TextArea1.Text = TextArea1.Text & "#"

Il risultato nella mia TextArea è il seguente:
Codice: [Seleziona]
forse#per#chèdellafatelquietetuseil'i#mma#goam#esicaravie#niosera.

Premettendo che Arduino mi trasmette i caratteri di continuo, non ci sono "strane" temporizzazioni.

Mi verrebbe da fare così:

MioBufferSeriale = MioBufferSeriale & s

e con un timer, dopo 5-6 secondi, vado a stampare MioBufferSeriale nella TextArea1.
Ma non mi sembra il massimo dell'efficienza.
Il tutto senza andare a scomodare il controllo della seriale (DTR/RTC/CTS etc. etc.).
Quale sarebbe il metodo più efficiente?

Offline fsurfing

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.484
    • Mostra profilo
non ho capito il problema

ti lascio un codice di prova di gambas e arduino, in cui i valori delle porte analogiche viene inviato da arduino a gambas, vedi se ti può servire
ps, sicuramente il codice non è ottimale è solo una prova

Offline El Berto

  • Grande Gambero
  • ***
  • Post: 150
    • Mostra profilo
Non riesco ad aprire il file:
Citazione
Si è verificato un errore durante il caricamento dell'archivio.
tar: unrecognized option '--no-wildcards'
Try `tar --help' for more information.

Quello che vorrei sapere è perchè il buffer della seriale mi legge un numero di caratteri variabile: al primo passaggio mi ritrovo solo la stringa "forse", poi mi arriva la stringa "per", poi quella "chèdellafatalquietetuseil'i".... e così via.

Comunque, adesso mi compare l'errore
Citazione
gambas gtk_text_buffer_emit_insert: assertion `g_utf8_validate (text, len, NULL)' failed
Ipotizzo che sia perchè mi arrivino alla porta seriale caratteri nulli (00h) che però devo riuscire a leggere.

Cercando ho trovato questo:
Codice: [Seleziona]
' Watching a serial port
DIM hFile AS File
hFile = OPEN "/dev/ttyS0" FOR READ WRITE WATCH

...

PUBLIC SUB File_Read()
  DIM iByte AS Byte
  READ #hFile, iByte
  PRINT "Got one byte: "; iByte
END

Ma non ho alba di come implementarlo per effettuare la lettura in tempo reale.

Offline El Berto

  • Grande Gambero
  • ***
  • Post: 150
    • Mostra profilo
Oltre a questo sto cercando di gestire la comunicazione seriale via hardware:

Sport.FlowControl = Sport.Hardware

Poi, provando a impostare le varie configurazioni di Sport.RTS e Sport.DSR, il modem comunque continua a trasmettermi i dati.....

Offline fsurfing

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.484
    • Mostra profilo
premesso che non ho assolutamente idea di come funzioni un collegamento seriale,  a naso direi che è impossibile inviare una stringa così lunga in un colpo solo, percui è normale che questa venga spezzettata, secondo me è meglio inviare la stringa antecedendogli un carattere di controllo e facendola terminare con un altra, così poi puoi ricostruire correttamente i dati trasmessi indipendentemente dal tempo che impiega arduino/gambas a trasmetterli/riceverli

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: [RISOLTO]: Lettura dati provenienti da Arduino mediante porta Seriale
« Risposta #10 il: 07 Gennaio 2013, 17:07:37 »
Trattandosi di "seriale", il trasferimento dei dai è appunto "seriale", ovvero un byte per volta, per cui l'interpretazione del blocco non è corretta.

Non ho idea di come funziona la libreria di gambas, non gli ho dato un'occhiata, ma penso che la ricezione dei caratteri avvenga tramite una logiga non interrupting, ovvero leggendo il buffer a tempo e/o a mezzo di logica analoga (es. un polling sullo stato dei segnali di controllo).

Secondo me puoi attivare du logiche parallele, ovvero capire quanto inizia e termina un messaggio, e attivare un timer di timeout, che viene resettato dalla ricezione dell'ultimo byte, onde evitare che scatti.
Una volta che hai ricevuto tutto il buffer, la logica soprastante lo preleva e ci fà quello che deve, reimpostando la trasmissione per la ricezione successiva.
Per evitare di perdere dati, potresti impostare una fifo, che accoda i caratteri che la seriale riceve, in modo che non ti perdi nulla, e da questa estrai mano mano le stringhe in modo più comodo...

Offline El Berto

  • Grande Gambero
  • ***
  • Post: 150
    • Mostra profilo
Re: [RISOLTO]: Lettura dati provenienti da Arduino mediante porta Seriale
« Risposta #11 il: 07 Gennaio 2013, 18:00:34 »
Purtroppo dal lato di trasmissione la cosa non la gestisco io; a volte vengono trasmesse delle stringhe (quindi c'è spesso una pausa), a volte mi vengono trasmessi blocchi da 2-3 KByte.

Attualmente ho impostato un timer che viene azzerato a ogni ricezione, quando smette di trasmettere (dopo 500 ms) mi entra nel timer e lì vado a leggere il buffer di ricezione.
Il problema lo trovo quando mi trasmette i blocchi da 2 kBytes, non so se per la dimensione del blocco o se è perchè mi trasmette tanti caratteri nulli, anche consecutivi.

Non so in base a cosa, ma con il codice fornito nell'esempio

Codice: [Seleziona]
Public Sub SPort_Read()  
 Dim s As String 
   
   Read #Sport, s, Lof(Sport)   

riuscivo a leggere massimo circa 80-100 Bytes (anche senza andarli veramente a leggere, se mettevo un semplice contatore, mi raggiungeva questi valori).

Poi ho provato questo codice che ho trovato nella lettura di un socket TCP:

Codice: [Seleziona]
WHILE Lof(LAST) > 0
   READ #Sport, s, 1
   RxData[ByteCount] = Asc(s,1)
   ByteCount += 1
WEND

Non capisco esattamente che differenza ci sia tra i due (se è per il fatto che nel calcolo della lunghezza di una stringa più caratteri nulli mi creano problemi), ma così mi funziona molto meglio.