Go Down

Topic: *RISOLTO* Utilizzo laser lidar con servi, rallentamenti e problematiche elettr.. (Read 733 times) previous topic - next topic

aldoz

Ciao a tutti,

Ho preparato il nuovo codice per la scansione del terreno del mio robot; davvero grande
risultato (molto migliore del precedente) seppur e' ancora un po troppo lento (ma il problema non è questo).

La mia configurazione:
Arduino MEGA2560
Lidar-lite v2
Adafruit 16channel servo board
2 servi

Il lidar è connesso al 5V, GND, SDA, SCL
l'Adafruit è connessa al 5V, GND, SDA, SCL (più alimentazione da alimentatore esterno dedicata ai servi)
I servi sono connessi all'Adafruit.
Non uso nessun componente elettrico tipo resistenze o altro.


Praticamente con questo codice la testa laser fa un su e giu' con contemporaneo rotazione in roll.
Ottengo una scansione di circa 150° di roll e 80° in pitch trasmessa, punto per punto a processing che visualizza appunto la scansione.

I problemi sono 2:
1) almeno 1 volta su 3 la scansione ad'un certo punto rallenta improvvisamente!; tutto il codice rallenta di oltre il 50%.
Se faccio ripartire la scansione, si riparte con la velocita' ridotta.
Anche compilare uno sketch vuoto per poi ricompilare da capo non cambia la situazione; la scansione a questo punto sara' sempre rallentata..
unica soluzione per riavere una scansione alla velocita' corretta è staccare e riattaccare il cavo USB che va da PC alla MEGA2560.
Una volta riattaccato il cavo, riavvio la scansione che riparte con la velocita' giusta senza rallentamenti.
Ovviamente fino alla volta in cui all'improvviso, durante la scansione, ritornera' il rallentamento.

2) Se invece di utilizzare la rete elettrica per alimentare i servi e USB per alimentare la MEGA, decidessi di utilizzare una batteria LIPO (potete vedere lo schema) per alimentare i Servi e per alimentare anche la MEGA, ottengo, oltre che il problema del punto 1, anche un blocco improvviso dell'esecuzione dello sketch, senza messaggi di errore ne sull'IDE Arduino ne in quello processing.
Blocco totale, freeze del codice; ogni volta che eseguo il codice dopo pochi istanti o pochi secondi dall'inizio della scansione.
Se riavvio lo sketch, esso riparte ma inevitabilmente dopo pochi istanti si riblocca tutto; un po prima o un po dopo ma si bloccherà inevitabilmente tutto.
(ricordo che il codice è lo stesso che ho usato utilizzando la rete elettrica)

PS: Ho eseguito questo codice sia utilizzando la libreria l2c sia utilizzando quella wire e non cambia nulla, stessi due problemi.

Qui di seguito il codice e lo schema utilizzando la batteria LIPO (tale schema mostra anche sensori tattili e giroscopio; non c'entrano nulla in questo caso ma lo schema elettrico comunque e' quello).

Code: [Select]
#define    LIDARLite_ADDRESS   0x62          // Default I2C Address of LIDAR-Lite.
#define    RegisterMeasure     0x00          // Register to write to initiate ranging.
#define    MeasureValue        0x04          // Value to initiate ranging.
#define    RegisterHighLowB    0x8f          // Register to get both High and Low bytes in 1 call.
#include <I2C.h>
//#include <Wire.h>

#include <Adafruit_PWMServoDriver.h>
// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

//LASER PITCH
int SERVOMIN_las1 = 150;  //LASER PITCH
int SERVOMAX_las1 = 600;  //LASER PITCH
//LASER ROLL
int SERVOMIN_las2 = 180;  //LASER PITCH
int SERVOMAX_las2 = 630;  //LASER PITCH

int pulselengthlas1, pulselengthlas2;
int direzione_laser = 0;
int cronoz = 0;
int fase_laser = 1;
int pos_laserpitch_fin = 60; //60  diminuendo la testa cabra, aumentando picchia.
int pos_laserroll_fin = 30; //30  

void setup()
{

  I2c.begin();          // Opens & joins the irc bus as master
  delay(100);        // Waits to make sure everything is powered up before sending or receiving data  
  I2c.timeOut(50);    // Sets a timeout to ensure no locking up of sketch if I2C communication fails

  Serial.begin(500000);//115200 57600

  pwm.begin();
  pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates (STO USANDO SERVI A 125hz)
  go_servi();
}



void loop()
{  
cronoz = cronoz + 1;
if(cronoz > 1500)
{
  //------------------------------------------- FASE LASER 1 PITCH DA 60 a 140
  if(fase_laser == 1)
  {
     if(pos_laserpitch_fin <= 140)
     {
       pos_laserpitch_fin = pos_laserpitch_fin + 1;
       GetDist();
       //delay(1);

     }  
     else
     {
      fase_laser = 2;
     }      
  }//fine fase 1  


  //------------------------------------------- FASE LASER 2 ROLL DI 3
  if(fase_laser == 2)
  {
    if(direzione_laser == 0)//*********************** da sinistra a destra ***************************
    {
          if(pos_laserroll_fin < 150)
          {
           //deve fare almeno 12 steps X
           pos_laserroll_fin = pos_laserroll_fin + 3;
           fase_laser = 3;
          }
          else
          {
            pos_laserroll_fin = 150;
            //direzione_laser = 1;//da destra a sinistra
            fase_laser = 9;
          }
    }//fine direzione laser = 0            
  }//fine fase laser 2

  
  //------------------------------------------- FASE LASER 3 PITCH DA 140 a 60
  if(fase_laser == 3)
  {
    
     if(pos_laserpitch_fin >= 60)
     {
       pos_laserpitch_fin = pos_laserpitch_fin - 1;
       GetDist();
       //delay(1);

     }  
     else
     {
      fase_laser = 4;
     }  
  }//fine fase laser 3


  //------------------------------------------- FASE LASER 4 ROLL DI 3
  if(fase_laser == 4)
  {
    if(direzione_laser == 0)//*********************** da sinistra a destra ***************************
    {
          if(pos_laserroll_fin < 150)
          {
           //deve fare almeno 12 steps X
           pos_laserroll_fin = pos_laserroll_fin + 3;
           fase_laser = 1;
          }
          else
          {
            pos_laserroll_fin = 150;
            //direzione_laser = 1;//da destra a sinistra
            fase_laser = 9;
          }
    }//fine direzione laser = 0          
  }//fine fase laser 3

}//fine cronoz  

go_servi();
}//fine loop



void go_servi()
{
      //SETTAGGIO INIZIALE LASER PITCH
      pulselengthlas1 = map(pos_laserpitch_fin, 0, 180, SERVOMIN_las1, SERVOMAX_las1);
      pwm.setPWM(15, 0, pulselengthlas1);      

      //SETTAGGIO INIZIALE LASER ROLL
      pulselengthlas2 = map(pos_laserroll_fin, 0, 200, SERVOMIN_las2, SERVOMAX_las2);
      pwm.setPWM(3, 0, pulselengthlas2);    
}      

 
void GetDist(){
  //-----------------------------------------------------------------------------------------
  //-------------------------------------------------------- LASER
  //-----------------------------------------------------------------------------------------
  // Write 0x04 to register 0x00
  uint8_t nackack = 100; // Setup variable to hold ACK/NACK resopnses    
  while (nackack != 0)
  { // While NACK keep going (i.e. continue polling until sucess message (ACK) is received )
    nackack = I2c.write(LIDARLite_ADDRESS,RegisterMeasure, MeasureValue); // Write 0x04 to 0x00  
    delay(1); // Wait 1 ms to prevent overpolling
  }

  byte distanceArray[2]; // array to store distance bytes from read function
  
  // Read 2byte distance from register 0x8f
  nackack = 100; // Setup variable to hold ACK/NACK resopnses    
  while (nackack != 0)
  { // While NACK keep going (i.e. continue polling until sucess message (ACK) is received )
    nackack = I2c.read(LIDARLite_ADDRESS,RegisterHighLowB, 2, distanceArray); // Read 2 Bytes from LIDAR-Lite Address and store in array        
   delay(1); // Wait 1 ms to prevent overpolling
  }
  
  int distancex = (distanceArray[0] << 8) + distanceArray[1];  // Shift high byte [0] 8 to the left and add low byte [1] to create 16-bit int
  Serial.print(pos_laserroll_fin);
  Serial.print(",");
  Serial.print(pos_laserpitch_fin);
  Serial.print(",");
  Serial.println(distancex);
}




Maurotec

Quote
Se faccio ripartire la scansione, si riparte con la velocita' ridotta.
Anche compilare uno sketch vuoto per poi ricompilare da capo non cambia la situazione; la scansione a questo punto sara' sempre rallentata..
unica soluzione per riavere una scansione alla velocita' corretta è staccare e riattaccare il cavo USB che va da PC alla MEGA2560.
Una volta riattaccato il cavo, riavvio la scansione che riparte con la velocita' giusta senza rallentamenti.
Ho come l'impressione che ad un certo momento il buffer della seriale sia pieno, cioè da processing leggi da seriale lentamente. Vedo che inizializzi la seriale a 500 000, quindi ho riduci la velocità di trasmissione o aumenti il buffer della seriale (credo serva modificare il core di arduino) oppure ancora controlla il codice lato PC (processing) è trova un modo di leggere più rapidamente.

Però lato processing credo riempirai un vettore con i dati ricevuti (e quindi è rapido), poi però questi dati li processi ed è forse qui che perdi tempo.

Ciao.

aldoz

Ho come l'impressione che ad un certo momento il buffer della seriale sia pieno, cioè da processing leggi da seriale lentamente. Vedo che inizializzi la seriale a 500 000, quindi ho riduci la velocità di trasmissione o aumenti il buffer della seriale (credo serva modificare il core di arduino) oppure ancora controlla il codice lato PC (processing) è trova un modo di leggere più rapidamente.

Però lato processing credo riempirai un vettore con i dati ricevuti (e quindi è rapido), poi però questi dati li processi ed è forse qui che perdi tempo.

Ciao.
Ciao Mauro, non e' che leggo lentamente da processing!
Che io avvii o meno processing, il problema appare! (anche da terminale seriale di Arduino o senza aprire ne terminale Arduino ne processing!)
quindi non e' legato a processing!
Poi purtroppo tale problema avviene sia utilizzando la seriale con 115200, con 57600, con 500000...

Oltretutto se tolgo il codice GetDist() (quello che gestisce il laser) l'applicazione va mooolto piu' veloce.
Senza tale codice la testa laser va oltre che al doppio della velocita'.
Possibile che un codice cosi' piccolo (quello appunto dentro GetDist() ) causi gia' un tale crollo di prestazioni? (che poi appunto viene, 1 volta su 3, ulteriormente rallentato dal problema 1)



Claudio_FF

Possibile che un codice cosi' piccolo (quello appunto dentro GetDist() ) causi gia' un tale crollo di prestazioni? (che poi appunto viene, 1 volta su 3, ulteriormente rallentato dal problema 1)
Se ad ogni ciclo di quella parte di codice vai a scrivere sulla seriale direi di si... Se togli la scrittura seriale da li cosa succede?
********* IF e SWITCH non sono cicli ! *********
**** Una domanda ben posta è già mezza risposta ****
*** La corrente si misura in mA, la quantità di carica in mAh ***

aldoz

Se ad ogni ciclo di quella parte di codice vai a scrivere sulla seriale direi di si... Se togli la scrittura seriale da li cosa succede?
Ciao Claudio, allora, rimuovendo tutti i Serial.print dal codice getDist(), la velocita' di esecuzione standard rimane invariata e anche la problematica del punto 1 si presenta
con il suo super rallentamento... e per ritornare alla velocita' standard devo staccare e riattaccare il cavo usb..
:\

mmmm

aldoz

Allora, ho modificato 2 tlinee all'interno di getDist():

uint8_t nackack = 50; // Setup variable to hold ACK/NACK resopnses
prima era 100

nackack = 50; // Setup variable to hold ACK/NACK resopnses 
e anche in questa linea di codice prima era 100

Con queste 2 modifiche, dopo circa una decina di scansioni, non ho piu' riscontrato il rallentamento improvviso (che prima era risolvibile solo togliendo il cavo usb)   

Quindi il primo dei problemi risolto!

Per quanto riguarda il problema 2? quello relativo all'uso della lipo..
qualche idea?



aldoz

purtroppo anche avendo cambiato quelle linee di codice il problema
del rallentamento oggi e' tornato..

mah non so proprio che pensare.. comunque sembra proprio un intasamento di dati.. tipo collo di bottiglia improvviso.

EDIT:
ho ridotto ulteriormente uint8_t nackack in entrambe le linee da 50 a 25.
e ho ottenuto scansioni davvero perfette e veloci!
in bassa risoluzione 6 secondi, in media 8 secondi, in medioalta 11 secondi e in alta risoluzione 45 secondi. (ottenendo su processing un point cloud)
diciamo che la problematica del rallentamento, su scansioni rapide non esiste.
Quando si creano molti punti si vede che l'accumulo di misurazioni affatica il sistema.
Poi ho notato, con stupore, che se il laser "vede" un oggetto vicino, impiega piu' millisecondi per stipare tale punto.
tant'e' che le scansioni dove non metto oggetti vicini sono piu' rapide di quelle in cui avvicino oggetti al laser.

Rimane il problema numero 2 che sinceramente mi destabilizza.. l'uso della batteria è indispensabile per il mio robot e non comprendo quale sia la problematica..
Mi viene in mente che quando attacco la MEGA via usb al pc, le lucine della suddetta hanno una intensita' ma quando accendo la batteria, noto che tali lucine diventano piu' accese..
sovra alimentazione?? aiuto!

Maurotec

Quote
Quando si creano molti punti si vede che l'accumulo di misurazioni affatica il sistema.
Poi ho notato, con stupore, che se il laser "vede" un oggetto vicino, impiega piu' millisecondi per stipare tale punto.
tant'e' che le scansioni dove non metto oggetti vicini sono piu' rapide di quelle in cui avvicino oggetti al laser.
Mai avuto esperienza con LIDAR, pertanto d'istinto io cercherei di capire come funziona il LIDAR così da sapere cosa posso aspettarmi.

Quote
Mi viene in mente che quando attacco la MEGA via usb al pc, le lucine della suddetta hanno una intensita' ma quando accendo la batteria, noto che tali lucine diventano piu' accese..
sovra alimentazione?? aiuto!
Puoi usare un tester per misurare la differenza di potenziale in volt?

Dallo schema vedo che userai la lipo connessa al convertitore 2.0A e l'uscita di questo a 5V la usi per alimentare la logica della scheda di ADA. Inoltre poi ci vorresti anche alimentare la MEGA per rendere tutto wireless. Poi vedo il convertitore 10A per alimentare i servo e questo forse è quello che crea maggiori disturbi di linea, ma solo quando lavorano i servo.

Certo se noti una variazione di luminosità dei led potrebbe anche essere perché la USB eroga circa 4.75V , mentre l'alimentare eroga 5.2V. Ti serve un tester per misurare le tensioni così da essere sicuro di non friggere nulla.

Ciao.

aldoz

Mai avuto esperienza con LIDAR, pertanto d'istinto io cercherei di capire come funziona il LIDAR così da sapere cosa posso aspettarmi.

Puoi usare un tester per misurare la differenza di potenziale in volt?

Dallo schema vedo che userai la lipo connessa al convertitore 2.0A e l'uscita di questo a 5V la usi per alimentare la logica della scheda di ADA. Inoltre poi ci vorresti anche alimentare la MEGA per rendere tutto wireless. Poi vedo il convertitore 10A per alimentare i servo e questo forse è quello che crea maggiori disturbi di linea, ma solo quando lavorano i servo.

Certo se noti una variazione di luminosità dei led potrebbe anche essere perché la USB eroga circa 4.75V , mentre l'alimentare eroga 5.2V. Ti serve un tester per misurare le tensioni così da essere sicuro di non friggere nulla.

Ciao.
mmm interessante.
Forse dovrei configurare (con le vitine addette allo scopo) lo step-down piccolo (quello da 2A) da 5V a poco meno di 5V?

E come potrei intervenire per i presunti disturbi della linea? il cablaggio è corretto; nel senso che tutto parte.. come potrei intervenire eventualmente?

Con il tester dovrei controllare i pin di uscita dello step down da 2A; corretto?
e dovrebbe corrispondere a 4,7v per essere identici alla tensione della usb?

Maurotec

Quote
Con il tester dovrei controllare i pin di uscita dello step down da 2A; corretto?
e dovrebbe corrispondere a 4,7v per essere identici alla tensione della usb?
La vite la devi regolare per avere 5.0 o 5.1V. La tensione della USB senza assorbimento dovrebbe essere di 5.0V ma ho verificato che non sempre è così su tutti i PC, inoltre in base alla lunghezza del cavo USB e alla sezione, ai capi del cavo stesso cade una tensione che aumenta con l'aumentare della corrente assorbita dal circuito. Ciò fa si che sul circuito tu misuri es 4.8V o ancora meno se assorbi più corrente.

Quote
E come potrei intervenire per i presunti disturbi della linea? il cablaggio è corretto; nel senso che tutto parte.. come potrei intervenire eventualmente?
Poi si vede in genere prima si trova la causa e poi si pensa a come affrontarla. Comunque in genere condensatori, induttanze, diodi e cablaggio sono le ricette.

Per il momento il tuo obbiettivo è rendere wireless il tutto senza guastare nulla, con questa certezza vai avanti verso il prossimo obbiettivo. Obbiettivo che si riduce a puntare il dito verso un colpevole ovviamente a raggion veduta.

Ciao.


Claudio_FF

E come potrei intervenire per i presunti disturbi della linea? il cablaggio è corretto; nel senso che tutto parte.. come potrei intervenire eventualmente?
Dall'alimentatore 5V parti a stella con linee diverse verso i vari componenti (Arduino, lidar ecc), e vicino a ciascuno di essi metti in parallelo un condensatore 47µF, in questo modo rapidi assorbimenti in una parte influiscono il meno possibile sulle altre (salvo che il regolatore o la batteria non ce la facciano). Se invece parti con un unico doppino dal regolatore e in giro "spilli" l'alimentazione vicino a dove serve, ogni elemento  alimentato dal doppino risente direttamente degli sbalzi di assorbimento di ogni altro.
********* IF e SWITCH non sono cicli ! *********
**** Una domanda ben posta è già mezza risposta ****
*** La corrente si misura in mA, la quantità di carica in mAh ***

aldoz

Claudio so che è una richiesta un po particolare.. ma siccome non ho ben chiaro come dovrei fare il collegamento che descrivi (partire a stella..?), potresti finire di "compilare" l'immagine dello schema che sto allegando?

Se non puoi non preoccuparti!!


Claudio_FF

Dal regolatore parti con tre rossi e tre neri.
Nei punti di arrivo (Ardu, relé, laser) metti a cavallo dell'alimentazione i condensatori.
Se ci sono più cose parti con altrettante coppie dal regolatore (in particolare nel primo schema vedo un adafruit servo giallo che mi sembra il più probabile generatore di disturbi sull'alimentazione.
********* IF e SWITCH non sono cicli ! *********
**** Una domanda ben posta è già mezza risposta ****
*** La corrente si misura in mA, la quantità di carica in mAh ***

aldoz

Dal regolatore parti con tre rossi e tre neri.
Nei punti di arrivo (Ardu, relé, laser) metti a cavallo dell'alimentazione i condensatori.
Se ci sono più cose parti con altrettante coppie dal regolatore (in particolare nel primo schema vedo un adafruit servo giallo che mi sembra il più probabile generatore di disturbi sull'alimentazione.

Claudio come capirai in ambito di elettricita' e impianti sono privo di esperienza..
ma forse ho capito, dopo cena posto lo schema cosi' mi dirai se c'ho azzeccato!

A dopo e grazie davvero per il supporto!

aldoz

Ok ecco qui lo schema..
sperando di aver azzeccato.. :)

PS. alla scheda adafruit e' gia' collegato un condensatore da 3300 uF



https://learn.adafruit.com/16-channel-pwm-servo-driver?view=all

Quote
Adding a Capacitor to the thru-hole capacitor slot
We have a spot on the PCB for soldering in an electrolytic capacitor. Based on your usage, you may or may not need a capacitor. If you are driving a lot of servos from a power supply that dips a lot when the servos move, n * 100uF where n is the number of servos is a good place to start - eg 470uF or more for 5 servos. Since its so dependent on servo current draw, the torque on each motor, and what power supply, there is no "one magic capacitor value" we can suggest which is why we don't include a capacitor in the kit.

Go Up