Protocollo per invio LIDAR scan data via seriale

Ciao a tutti,
Ho un problema nel trasferire in maniera efficiente dei dati da arduino al pc.
Ho un laser scanner collegato all'arduino , (Seeed Studio Bazaar, The IoT Hardware enabler.) , lo scanner fornisce una coppia di dati float (angolo, e distanza) ogni circa 0.5 ms e quindi uno scan rate di 360° in 180 ms.
questi dati arrivano in continuo dallo scanner è quindi fondamentale che il codice sia ottimizzato per non perderne dei pezzi per strada :slight_smile:

Ora il problema è trasferire i dati al PC via seriale Rs485 , attualmente sto usando il Modbus ma è troppo lento e riesco a bufferizzare solo 1 scan per secondo perdendo in pratica 4 scan su 5. Ho bisogno della Rs485 perchè la distanza fisica tra pc e scanner potrà essere anche di 100 mt...

L'idea era implementare un protocollo semplice, tipo $,angle1,distance1,angle2,distance2,.... angle360,distance360...#

Se qualcuno ha tempo e voglia di scrivermi qualche dritta su come impostarlo, se per esempio è meglio bufferizzare uno scan intero e spedirlo oppure spedire la singola coppia di dati.

Attualmente sto usando un Arduino Mega ma per la versione finale vorrei usare un DUE per avere maggiore velocità di calcolo.

Dal lato Pc un client in VisualStudio farà il parse della stringa e visualizzerà la scansione.

Grazie in anticipo

Flavio

La velocitá della interfaccia RS485 é limitata. Per avere la trassmisione di dati nel tempo minore possibile devi risparmiare dati trasmessi oppure bufferizzarli.

Non é necessario che invii per ogni dto l’ angolo ma solo all inizio di quanto e l’ angolo tra due misure.

Ciao Uwe

Ciao Uwe,
la coppia di dati mi sa che sono costretto a inviarla completa perché per ogni scansione il laser mi invia 360 coppie di dati in sequenza ma l'angolo per ogni coppia di dati è un float a due decimali di un grado

per esempio:

angolo1 = 0.4 distanza1 = 500.45
angolo2 = 1.7 distanza2 = 507.47
...
...

nella scansione successiva l'angolo è diverso, anche se sempre compreso nell'intero di un grado
angolo1 = 0.7 distanza1 = 510.77
angolo2 = 1.4 distanza2 = 509.99
...
angolo360 ... distanza360...

essendo che lo scopo è poi trasformare in coordinate cartesiane il punto, la precisione dell'angolo è importante per la risoluzione globale.

Esiste qualche protocollo già implementato che permette l'invio pacchetti di float ?
Attualmente con il modbus, bufferizzo 60 coppie di dati alla volta e riesco a mantenere un baudrate della seriale a 115200 n81 fino a 120 mt su copiola schermata, spero ottimizzando il protocollo di riuscire a inviare le 360 coppie in un unico pacchetto.

Poi dal lato client mi adeguo per la lettura, il parsing e la visualizzazione

Vediamo se ho compreso bene il problema.
Hai un valore angolare da 0 a 359,9 gradi ed un valore lineare da 0 a 600.00 cm

Con il float occupi 2 x 4 = 8 byte per ogni coppia di valori, ma se con Arduino converti i valori da float ad unsigned int risparmi il 50% di spazio cioè solo 4 byte.

In pratica, avresti per il valore angolare una variazione tra 0 e 3599, mentre per il valore lineare una variazione tra 0 e 60000, perfettamente rientrante nel range di unsigned int (0-65535).

Questo ridurrà le dimensioni del buffer da gestire, oltre a velocizzare la trasmissione.

Resta solo da vedere se la conversione è abbastanza veloce: sicuramente lo è per la DUE, ma credo che anche la MEGA ce la faccia.

Ciao CyberHs,
I dati erano casuali, l'angolo è un float con 2 decimali quindi 0.00 a 359.99 la distanza è anchessa float con due decimali e va da 0.00 a 6999.99 in mm ( 7 mt ).
Per me sarebbe accettabile troncare l'ultimo decimale di entrambe le misure, ma con la distanza sia fuori dal range degli int :frowning:

Non conosco lo RPLIDAR ma dalle caratteristiche leggo che le misure angolari hanno una risoluzione inferiore al grado (cioè 0.1° al massimo) , mentre quelle lineari inferiori a 0.5mm (cioè 0.1 mm al massimo).
Perciò a mio avviso puoi scartare tranquillamente i centesimi di grado ed i centesimi di millimetro.
Però è vero che non puoi andare oltre il 6553,5 millimetri, ma non mi sembra un grave problema.

Hai qualche idea su come strutturare la stringa per ottimizzare la velocità del loop ?
Ho poca dimestichezza con il "consumo" di risorse in funzione delle istruzioni scritte, ad esempio nei test facevo un cast da float a char per poi inviare sulla seriale che rallentava il loop in maniera significativa :cold_sweat:

Che protocollo ha in uscita lo RPLIDAR? (None, Xon-Xoff o cosa?)
Che caratteri di controllo? (carattere inizio coppia, fine coppia, inizio/fine pacchetto o cosa?)
Che baud rate è impostato?

I dati in uscita dal Lidar li leggo tramite la libreria già implementata nell’SDK del laser quindi il protocollo che devo implementare è solo tra Arduino e PC , in sostanza leggo il Lidar sulla Serial1 e invio al PC da Serial2 tramite tranceiver uart/rS485 , la coppia di dati dal Lidar è aggiornata ogni loop quindi si potrebbe inviare la coppia oppure bufferizzare N coppie e inviarle.

  if (IS_OK(lidar.waitPoint())) {
    
    float distance = lidar.getCurrentPoint().distance; //distance value in mm unit
    float angle    = lidar.getCurrentPoint().angle; //anglue value in degree
    
    int distance_mm = (int)(distance);  //cast a mm
    int angle_int = (int)(angle); // cast a gradi interi

    if (angle_int < 361){  // verifico che la matrice non esca dai limiti
   
 regs[angle_int] = distance_mm;  // aggiorno il registro relativo all'angolo
    
    }

questa è la funzione con cui ora aggiorno la matrice regs(360) , per semplificare con Angolo intero e con distanza in mm senza decimali per sfruttare la proprietà dei registri del Modbus , dal Client leggo il registro reg(0) e il valore è corrispondente all’angolo compreso tra 0 e 1 ° , ovviamente perdendo precisione a beneficio della velocità, quello che vorrei fare è eliminare il modbus e inviare i dati con un protocollo piu’ semplice e piu’ veloce.
Il modbus funziona con master/slave che si passano richieste e conferme , va bene per delle letture lente ma non in questo caso :frowning:

Non avendo la libreria, non so se sia possibile ottenere le varie coppie di dati già in formato unsigned int che sarebbe l'ideale.
E'possibile avere un link a questa libreria ovvero alle sue funzioni?

ecco la libreria