Go Down

Topic: Far comunicare GRBL e arduino uno (Read 11058 times) previous topic - next topic

axl936

Ciao!
dopo svariate ore passate a leggere forum e documentazioni varie, prima di cadere nella demoralizzazione, vorrei chiede a qualche buon anima se mi puo' aiutare a risolvere il mio problema !

Scenario:  (scusate ma sara' un post lungo !)
Ho un atmega 328 standalone con caricato Grbl 0.9e (funzionante e testato , sempre utilizzato inviando i dati tramite pc in seriale..)
Ho poi un arduino uno sul quale sto cercando di sviluppare questo  sw che mi fa dannare..
Questo secondo "giocattolo" lo chiamero' "master", mentre il 328 con grbl lo chiamero' "grbl" per cercare di spiegare..

Ora mi sono intestardito di voler utilizzare il master (che poi se tutto funzionera' diventera' un altro 328 standalone) per inviare i dati al "Grbl" tramite seriale prendendoli da una SD.

Ho fatto la parte hw, ho messo anche un lcd 16x2 per un debug immediato, visto che la seriale poi sara' dedicata solo alla comunicazione tra i 2 e non disponibile per il pc..
Fin qui tutto ok, se leggo le linee una ad una dalla SD e le "stampo" sull lcd , nessun problema, tutto corretto..
Se inoltre le invio via seriale (collegata per test/debug) al pc simulando di essere io tramite pc il grbl a ricevere/rispondere anche qui tutto ok !
Ho verificato con un programma di connessione seriale (su pc) con visualizzazione ascii ed esadecimale dei dati da e verso "grbl" ed escono corretti al byte, MA (!!) se collego tra loro i 2 questi si scambiano 1 o massimo 2 linee e poi si ferma il tutto miseramente !!
Il grbl restituisce degli errori come se i comandi fossero "malformati" anche se in realta' le linee di comando sono perfette ( provato piu' volte ad inviare le stesse da pc e le accetta benissimo..)
Pensavo fossero degli errori di comunicazione, dovuti a disturbi o velocita', (i 2 sono a 10 cm)
Ho provato ad abbassare la velocita', ma non cambia nulla
Mi sono messo col pc "sniffando" una alla volta le linee TX del grbl e del master usando un convertitore usb2ttl collegando solo la massa e la RX, in modo da non influire sulle comunicazioni, e la sequenza di byte che vedo passare in entrambi i sensi e' esattamente quella che mi aspetto mentre comunicano tra loro, MA QUALCOSA NON VA !!!
...Sto impazzendo (il caldo non aiuta..)

Per chi non lo conoscesse grbl e' un piccolo interprete di codice "G" che poi pilota i motori di varie cose, da stampanti 3d, pantografi cnc etc..
Da un certo punto di vista e' molto semplice.. alla partenza invia in seriale una stringa di "benvenuto" e poi sta li ad aspettare dei comandi via seriale, appunto !
Semplificando moltissimo il suo funzionamento, ad ogni CR (o LF, indifferentemente)  inviatogli lui risponde con un "ok"+CR+LF ad indicare che lo ha ricevuto

poi se si invia una stringa tipo "G0 x1 y2" +CR (o LF e' indifferente)  lui la prende in "carico" e risponde il solito "ok"+CR+LF
di queste stringhe ne accetta un tot, fino a riempire un buffer, ed il risultato e' che ad un certo punto inviandone una lui non ci restituira piu' il solito ok+... finche non avra' "smaltito" quelle gia' presenti nel buffer
A quel punto ci mandera' il solito ok e noi potremmo sparare in seriale altre stringhe e via dicendo..

Ho anche provato a fere un programmino molto ridotto eliminando al minimo le cose per cercare di uscirne, ma anche senza lettura da SD, dichiarando 5 stringhe di test scritte a mano e perfettamente testate e funzionanti ancora non vuole andare.
Ho introdotto ritardi di test ovunque, ma piu' ci sbatto e meno capisco..

Qualcuno mi aiuterebbe ??

Grazie !



axl936

#1
Jun 24, 2014, 11:25 pm Last Edit: Jun 24, 2014, 11:32 pm by axl936 Reason: 1
Ah,
allego il codice ridotto all' osso della parte master..

funziona egregiamente se lo si testa tra master e pc, ma appena si collegano master e grbl invia una o 2 stringhe e poi grbl da errori come se la stringa inviata fosse "sbagliata" e poi si ferma tutto..

Code: [Select]


#include <Wire.h>              
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR  0x38  // indirizzo i2c del pcf..
#define BACKLIGHT_PIN     7
int lineNo = 0;

// stringhe di comandi di prova..
char* ComandoG[]={"g0 z10.00","G00 X0.000 Y0.000","G00 X-3.00 y0.00 Z5.000","G00 X-3.00 y0.00 Z0.000","G01 X-3.00 y0.00 Z-4.00 F250","X-0.00 Y-0.00 Z-4.00","g0 z5.00","g0 x0 y0"};

String RxString;
LiquidCrystal_I2C lcd(I2C_ADDR, BACKLIGHT_PIN, POSITIVE);  // Set the LCD I2C address

void setup()
{
 lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
 lcd.begin(16,2);        // inizilizzo l' lcd a 16 colonne per 2 righe
 lcd.setBacklight(HIGH);
 lcd.clear();
 lcd.print("Attesa GRBL..");
 
 delay(5000); // aspetto alcuni sec prima di iniziare ad inviare
 
// Open serial communications and wait for port to open:
 Serial.begin(57600); // velocita' di trasmissione seriale
 
 // sveglio GRBL :
 Serial.println(); // invio cr+lf (risponde con 2 ok di fila)
 delay(1000); // attendo un sec per la risposta
 Serial.flush();  // per sicurezza svuoto il buffer di ricezione

 lcd.clear();
 lineNo= 0 ;
   while (lineNo < 8)  // mi preparo ad inviare le 8 stringhe di test
     {
       Serial.print(ComandoG[lineNo]); // invio la stringa
       Serial.write(0x0A);      // seguita solo da /n (LF)
       lcd.print(ComandoG[lineNo]); // per debug la scrivo sull lcd
       lineNo++;
       delay(1000); // attesa per lettura informazioni su lcd

       // lettura della risposta da seriale e stampa su lcd della stessa..

       while (Serial.available() <=0) // Attendo che il buffer di ricezione contenga qualcosa in risposta
        {
            delay(5);
               }

       while (Serial.available()) // legge tutti i caratteri nel buffer
         {
         RxString += char(Serial.read()); // creo una stringa con i caratteri ricevuti
         delay(10);
         }

       lcd.print(String(lineNo) + "<" + RxString); // su lcd la stringa di risposta ricevuta
       delay(1000); // tempo per leggerla
       RxString="";

     } // file lettura risposta
 
 // dopo aver inviato le 8 stringhe, fine trasmissione
   lcd.clear();
   lcd.print("Fine invio !!");  
}

// fine programma

void loop()
{
delay(100);
// loop infinito che non fa niente !!
}



nid69ita

Ti invitiamo a presentarti qui: http://forum.arduino.cc/index.php?topic=113640.0
e a leggere il regolamento: http://forum.arduino.cc/index.php?topic=149082.0
- qui una serie di schede by xxxPighi per i collegamenti elettronici vari: http://forum.arduino.cc/index.php?topic=146152.0
- qui le pinout delle varie schede by xxxPighi: http://forum.arduino.cc/index.php?topic=151646.0
- qui una serie di link generali utili: http://forum.arduino.cc/index.php?topic=126861.0
my name is IGOR, not AIGOR

axl936

Ciao
Ho fatto ulteriori prove..
con un altro arduino ho lo stesso risultato, MA utilizzando la software serial al posto di quella HW invece la cosa cambia parecchio...
FUNZIONA !!!!
..Al primo colpo, senza grosse modifiche..

Adesso pero' il problema mi rimane..
Io vorrei usare la seriale hardware per vari motivi (buffer, flessibilita' etc..)
Cosa potrebbe essere a causare il difetto ?
E' come se i dati venissero inviati "sbagliati" o disturbati o "non sincronizzati" (o chissa cos' altro..), anche se dal pc risultano arrivare in ordine..
Forse il pc e' piu' "flessibile". ?!
E' possibile che la parte dell' adattatore ttl2usb (il 16u2) dell arduino in quialche modo possa disturbare la comunicazione dei "pin" 0 e 1  essendo pratica,mente collegato assieme ad essi ?

Qualcuno mi puo' dare qualche consiglio o work-around ?

Grazie
Axel

cyberhs

Vediamo se ho capito.
Tu usi una UNO con il programma che hai inviato per trasmettere lo G-code ad uno "stand alone".
Non vedo il programma ricevente: probabilmente è la sede dell'inghippo. 

axl936

Ciao cyberhs,
Grazie per avermi risposto, innanzitutto !

Il programma "ricevente" , il grbl in questione non lo posto perche' e' parecchio "ingombrante" ed articolato.
NON e' (purtroppo) farina del mio sacco, io mi limito ad utilizzarlo..
E' comunque open source e lo si trova qui:
https://github.com/grbl/grbl/tree/dev
lo si puo' comodamente consultare anche senza scaricarlo, direttamente dal web, giusto epr darci un occhiata..

Non mi sono addentrato a cercare di fare modifiche li' dentro perche' non credo di esserne in grado e per non peggiorare la cosa..

Se a passatempo o per curiosita' ci vuoi dare una sbirciata, per formulare qualche ipotesi che mi possa aiutare, mi faresti un gran regalo..
Grazie
Axel


cyberhs

Ma la UNO è collegata al PC via USB quando lanci il programma?

axl936

#7
Jun 26, 2014, 10:26 pm Last Edit: Jun 26, 2014, 10:33 pm by axl936 Reason: 1
Ciao
No, assolutamente no !
quando provo a farli comunicare tra loro la usb sulla UNO e' libera, e il "grbl" ha i tx e rx ovviamente collegati incrociati alla UNO e basta !

Fornisco alimentazione alla UNO tramite un alimentatore esterno da 9v DC che ho verificato con l' oscilloscopio non dare glitch e spurie varie..
Dalla UNO alimento anche la GRBL portando i +5 e gnd (anche sulla grbl ci sono i cond di filtro e livellamento vicinissimi al chip)

Ho appena fatto un ulteriore prova, ho messo su una breadbord SOLO il mega328 della UNO, un quarzo da 16 Mhz e i 2 relativi cond da 22pf
Ho collegato l' LCD per debug immediato via I2C (solo i pin SDA e SCL), alimentazione, condensatore di filtro da 100nf + uno di stabilizzazione da 22uF.
Ah, ovviamnete la resistenza di pullup per il reset.
Ho collegato il tx del 328 (ex UNO) al rx del grbl e tx del 328(ex UNO) al rx del grbl... null' altro !

IL RISULTATO NON CAMBIA...
Sull lcd dove vedo la risposta del grbl, mi arriva sempre errore ad ogni invio, per poi fermarsi..

Quindo ho escluso anche eventuali disturbi dovuti al 16u2... c'e dell' altro che mi sfugge !

Ah, ovviamente ho fatto la prova a SOSTITUIRE il grbl con il pc per vedere cosa arriva in seriale ed arriva tutto perfettamemnte come mi aspetterei !!!

Ancora, con questo hardware (2 mega328 standalone) se sul master (leggi il chip della UNO) carico lo sketch che utilizza la sw serial i due parlano beati come due vecchie signore !!! (ovviamente usando come tx e rx della UNO due pin diversi da quelli dedicati alla seriale hw)

IDEE ???



cyberhs

L'errore credo sia nella String  RxString.
Inizializzala usando tanti spazi quanti la lunghezza massima della stinga che devi ricevere più qualcosa.
String RxString = "                ";

axl936

ciao
..dici ??
Dopo provo e ti faccio sapere..
sarebbe bello se cosi' potessi risolvere..

Io cominciavo ad ipotizzare che non fosse un problema  di "cosa" spara in seriale, ma "quando" !
..nel senso che potrebbe inviare correttamente, ma che l'altro facesse la lettura in tempi "sbagliati" o troppo presto, o troppo tardi, prendendo come dato una parte incompleta del comando inviatogli.

per capirci se invece di prendere "g0 z10.00" cominciasse a "catturare" tardi lo stream e prendesse "0 z10.00" (senza la G iniziale per capirci) ci starebbe l'errore che restituisce, di comando errato
Anche se troncasse la fine dello stream (non prendendo che ne so il \n terminante) magari potrebbe rimanere nel buffer la striga che sommata alla successiva darebbe origine ad un comando senza senso..
Questo potrebbe essere il motivo per cui la comunicazione "si ferma".
Non sentendo il fine riga, lui non manda l' "ok" di avvenuta ricezione e l'altro non manda altro nell' attesa dell "ok"..
Ci sta'.. !
Un po tirato, faccio fatica a crederlo essendo hardware, ma ci potrebbe stare..

che ne pensi ?
Intanto provo il tuo work-around..
grazie ancora
ciao



axl936

Ho provato ad inizializzare la stringa come mi hai suggerito.. ho contato il comando piu' lungo tra quelli nell' array e la ho inizializzata alcuni caratteri piu' lunga..

niente.. stesso risultato..
Ho notato pero' che se modifico l' array di stringhe da inviare, mettendone una con un solo carattere , per esempio il "\n"  (LF), il grbl  a quella mi risponde subito con l' "ok", come dovrebbe essere, se solo aggiungo pochi caratteri es "G0X10\n" appena il master la invia, non ricevo nessuna risposta, gia' la comunicazione si ferma.
A questo punto ho provato ad inserire una piccola routine che fa in modo che se non ottengo nessuna risposta entro 3 secondi dopo l'invio di un comando , invio un altro "\n" (LF)...
Risultato:
l'invio del solo carattere \n ottiene immediatamente risposta, senza far subentrare la nuova routine, l'invio di stringhe appena piu' lunghe non ottinene risposta, dopodiche' passati i 3 secondi la routine invia un altro \n ed ottengo immediatamente come risposta un errore di comando non valido.

In realta' dovrei ottenere come risposta ben due "ok", uno per il primo LF (quello a terminazione del comando)  e uno per quello dopo i 3 secondi inviato dalla routine..

Questo mi conferma che il comando non viene ricevuto come dovrebbe..
Come dicevo, "sniffando" su quella linea (il TX del master (UNO) coillegato al RX del grbl) i dati che passano, mi vedo passare esattamente cio' che mi aspetto..

per esempio inviando "G0X10\n" mi vedo passare : 47 30 58 31 30 0A
ma non ho risposta dal grbl,... dopo i 3 sec mi vedo passare un nuovo 0A (sparato dalla routine), a quel punto come risposta mi arriva un errore di comando non corretto.
Inutile dire che provando ad inviare da pc lo stesso comando (e anche usando la soft serial con lo stesso identico sketch) il comando viene accettato tranquillamente e ricevo il mio bel ed atteso "ok"..

Mi sembra di essere il Dottor House..
Quote
Altro ?








cyberhs

C'è un aspetto che varrebbe la pena verificare.
A 57600 occorre necessariamente un sistema di handshaking per una corretta trasmissione e quello adottato è una versione di Xon/Xoff.
Il ricevente quando riempie il suo buffer invia un carattere di Xoff (0x13 = 19) per fermare la trasmissione e ne invia un altro Xon (0x11 = 17) per farla riprendere.
Prova a vedere se ricevi Xoff od altro.
Poi tu mandi la stringa seguita da LF (0x0A = 10) mentre normalmente si invia la sequenza CR + LF: sei sicuro che questa sia la normale sintassi?

axl936

#12
Jun 28, 2014, 05:25 pm Last Edit: Jun 28, 2014, 05:45 pm by axl936 Reason: 1
Hai perfettamente ragione sul sistema di handshaking..
Anche io speravo che ci fosse, ma da quello che vedo transitare non arriva null' altro che i comandi e' la terminazione con "CRLF"

Per la tua giusta osservazione riguardo alla terminazione col solo LF invece che CRLF come sarebbe piu' standard,
io mi sono rifatto allo script in python che forniscono gli stessi sviluppatori del grbl per fare il "porting" sull' arduino UNO da usare per inviare i comandi da pc al grbl.
Sono pochissime righe in python , se ci dai un occhio tanto per verificare se ho capito male io mi faresti una cortesia..

https://github.com/grbl/grbl/blob/master/script/simple_stream.py


lo riporto qui essendo molto breve..
Qui usano i 9600 ma nelle faq c'e scritto chiaramente che si puo' utilizzare tranquillamnte fino a 115200 solo cambiano la velocita' della seriale
Quote

import serial
import time

# Open grbl serial port
s = serial.Serial('/dev/tty.usbmodem1811',9600)

# Open g-code file
f = open('grbl.gcode','r'); ### file che contiene i comandi, uno per riga

# Wake up grbl
s.write("\r\n\r\n")
time.sleep(2) # Wait for grbl to initialize
s.flushInput() # Flush startup text in serial input

# Stream g-code to grbl
for line in f:
   l = line.strip() # Strip all EOL characters for consistency
   print 'Sending: ' + l,
   s.write(l + '\n') # Send g-code block to grbl --- comando terminato da 'n' (LF)
   grbl_out = s.readline() # Wait for grbl response with carriage return
   print ' : ' + grbl_out.strip()

# Wait here until grbl is finished to close serial port and file.
raw_input(" Press <Enter> to exit and disable grbl.")

# Close file and serial port
f.close()
s.close()


oppure uno sempre di loro provenienza un po piu' elaborato (ma comunque molto comprensibile e breve..) ma a parte la gestione  del buffer e qualche contgrollo in piu' il succo e' quello..


https://github.com/grbl/grbl/blob/master/script/stream.py


Di seguito riporto la comunicazione fatta da pc al grbl, tanto per non lasciare nulla al caso..
All' accensione collegandosi in seriale si riceve :

Quote

9A 0D 0A 47 72 62 6C 20 30 2E 39 65 20 5B 27 24 27 20 66 6F 72 20 68 65 6C 70 5D 0D 0A


i caratteri spampabili sono : Grbl 0.9e ['$' for help]
a questo punto invio un LF e ricevo immediatamente in cambio
Quote

6F 6B 0D 0A

il mio ok seguito da cr+lf

Adesso invio il comando "G0X10" seguito da LF
ed immediatamente risponde
Quote
6F 6B 0D 0A


Altri caratteri esadecimali non ne vedo passare, quindi credo che non ci sia un handshaking..

ho provato con stringhe di comando molto piu' lunghe ma mi restituisce sempre e solo l' "ok"
altri codici hex che non siano caratteri stampabili oppure 0D o 0A non ne vedo..

Se adesso provo ad inviare il comando di prima terminando la riga con CRLF anziche solo LF
questa e' la risposta:
quote]6F 6B 0D 0A 6F 6B 0D 0A[/quote]

2 ok di fila ! (con crlf a seguito per ogniuno)

Se invece invio il comando terminandolo con CR ricevo comunque il mio "ok"
Dunque lui accetta sia CR sia LF come terminazione di comando

Mettendoli ambedue semplicemente mi risponde 2 volte, accettandoli entrambi !



cyberhs

Hai provato a scendere a 9600 baud?

axl936

ciao
ho provato a ricompilare il grbl per andare a 9600 e di conseguenza settato il master a 9600...
Il risultato e' un pochino migliore, nel senso che non si blocca immediatamente, ma un paio di invii corretti li fa..
Se i comandi sono brevi anche 3 o 4 di fila, poi ricado nello stesso problema..

Mi pare di capire quindi che il problema e' proprio qualcosa legato alla temporizzazione delle 2 seriali..
..a sapere cosa pero' !..
Quello che non capisco e' perche' da pc il problema non si evidenzia..
Da pc va bene a 9600 a 57600 a 115200 anche inviando file di 500k.. non perde un colpo..
mistero !

Go Up