gbm
Robot self balancing con Arduino e 4 LED
Tutorials -
Venerdì 27 Gennaio 2012 07:51
Scritto da gbm

Con questo tutorial vedremo come creare un robot self balancing utilizzando unicamente 4 LED a infrarossi per determinare l'inclinazione del robot rispetto al terreno. Voglio sottolineare che, tendenzialmente la costruzione di un self balancing implica l'acquisto di una piattaforma inerziale con sensori MEMS, di solito molto costosa, noi invece cercheremo con questo tutorial di ottenere lo stesso risultato a costo trascurabile. Grazie all'algoritmo PID e al sensore di distanza LED analogico potremo in poche semplici righe di codice, costruire e sperimentare un sistema complesso come un automa in grado di rimanere in equilibrio e muoversi nello spazio.  Per ottenere questo risultato utilizzo la tecnica proposta nel self balancing per principianti, cioè il calcolo differenziale di due distanze tra struttura del robot e terreno. I due sensori sono posti sotto la parte anteriore e posteriore del robot, equidistanti dal centro. In questo caso, in posizione di perfetto equilibrio otterremo un valore prossimo a 0, < di 0 sbilanciando il robot in un senso e > 0 nel senso opposto.

 

Questo video mostra le mie sperimentazioni di Giugno 2011, in cui testavo la fattibilità di utilizzare i LED per percepire l'inclinazione. 

Come potete vedere dal video c'erano svariati problemi di base come delay nella reazione, ridotta risoluzione e drift dipendente dalle superfici che ai tempi ho considerato non risolvibili.

Questo perchè utilizzavo il reverse biasing, un metodo che misura il tempo di scarica del LED, piuttosto che la tensione prodotta da esso. Per cio' il robot aveva un refresh della sua posizione troppo lento e un output estremamente soggetto a interferenze. Il risultato è un self balancing che sta piu' o meno in piedi, visibilmente affetto dal Parkinson.

Dopo questi esperimenti ho iniziato a considerare altre possibili tecniche per la rilevazione dell'intensità luminosa con refresh rate piu' ridotti e con qualità dell'input maggiori.

 

Come potete vedere nel video sto utilizzando delle ruote da ben 10cm di diametro che permettono di recuperare situazioni in cui il robot è davvero molto inclinato. Questa scelta ovviamente riduce la fluidità dei movimenti, per questo consiglio piuttosto ruote da 8cm.

Per complicarmi ulteriormente le cose, ho posizionato il baricentro a pochi cm sopra l'asse delle ruote, il che rende ancora piu' difficile gestire l'inclinazione del robot. Per via della regola del pendolo inverso, è piu semplice tenere in equilibrio un corpo con baricentro spostato verso l'alto, piuttosto che il contrario. 

Tutto cio' per osservare una situazione "limite", in piu' ho utilizzato una doppia illuminazione abbastanza potente incandescenza e neon per mettere a dura prova i sensori.

Il risultato lo potete vedere nel video, secondo me piuttosto soddisfacente visto il costo dell'impresa e il tempo dedicato. Cercando "self balancing" su youtube, è possibile vedere robot all'opera con IMU che non fanno una figura migliore.

 

Per ottenere risultati piu' soddisfacenti del caso limite mostrato sopra e per un maggiore effetto consiglio di posizionare il baricentro in alto quanto i motori e la potenza a disposizione lo consentono. Inevitabilmente è necessario provare e spostare la massa piu' pesante (la batteria) per trovare il giusto compromesso. 

 

Il materiale

2x Kit sensore ERER wired 

1x Piattaforma Pico 1.1

2x Staffa microservi/sensori

2x Microservi

2x Ruote 10cm

2x StepUp 3.7v -> 5v

2x Lipo 3.7v 400ma

1x Arduino duemilanove

1x Mini breadboard

1x Protoshield

Se osservate i vecchi articoli, venivano utilizzati portabatterie da 4 AA, pesanti, poco efficienti e davvero molto inquinanti.

Sto testando con successo l'uso di celle singole al litio, derivate dal modellismo, davvero comode, affidabili e durevoli. Per utilizzarle è necessario collegarle a uno stepUp che alzi il voltaggio a 5v, per poi alimentare arduino e i servomotori con una cella singola.

Quello di cui ci si accorge subito è la riduzione del peso del robot, di conseguenza un aumento della velocità massima, accelerazione e riduzione dei tempi di arresto. Ovviamente il robot stesso consumerà meno corrente aumentando la propria autonomia.

La cosa piu' interessante è che queste celle 3.7v possono essere caricate direttamente dal pin 5v di Arduino, infatti esse contengono un circuito di carica che funziona proprio a 5v. In questo caso sarà possibile ricaricare la cella con le porte GND e 5v di Arduino quando connesso a USB o a una qualsiasi altra fonte di alimentazione.

 

Il codice

///    WWW.GIOBLU.COM - Giovanni Blu Mitolo 2012
/////  SELF BALANCING ROBOT
////// IR LED SENSORS USED TO DETERMINE ORIENTATION
Servo left;
Servo right;
///// VARIABILI SETUP  ////
int frontInputPIN = A0;
int frontEmitterPIN = 2;
int backInputPIN = A1;
int backEmitterPIN = 12;
int frontReadings = 37; // Esposizione sensore ant / post
int backReadings = 31;  // Variare x ottenere corretta inclinazione in stato di quiete
int kP = 10;  // Variabile setup PROPORZIONALE
int kI = 100;  // Variabile setup INTEGRATIVA
///////////////////////////
float time = 0;
int front = 1;
int back = 0;
int P = 0;
int I = 0;
int PID = 0;
int orientation = 0;
//////////////////////////

void setup() { 
  left.attach(11);
  right.attach(10);
  pinMode(frontInputPIN, INPUT);
  pinMode(backInputPIN, INPUT);
  pinMode(frontEmitterPIN, OUTPUT);
  pinMode(backEmitterPIN, OUTPUT);
  pinMode(3, OUTPUT);
  digitalWrite(3, LOW);
  Serial.begin(9600);
  left.write(90);
  right.write(90);
} 

double getDistance(boolean Front) {
  double intensity = 0;
  double ambient = 0;
  int readings = (Front) ? frontReadings : backReadings;
  digitalWrite((Front) ? frontEmitterPIN : backEmitterPIN, LOW); // Lettura ambientale
  for(int i = 0; i < readings; i++) {
     ambient = ambient + analogRead((Front) ? frontInputPIN : backInputPIN);
  }
  digitalWrite((Front) ? frontEmitterPIN : backEmitterPIN, HIGH); // Lettura attiva
  for (int i = 0; i < readings; i++) {
    intensity = intensity + analogRead((Front) ? frontInputPIN : backInputPIN);
  } 
  intensity = intensity - ambient; // Filtro luce ambientale
  return intensity;
}

void getOrientation() {
  float previousTime = time;
  time = millis();
  float cycleTime = time - previousTime;
  orientation = getDistance(front) - getDistance(back);
  kP = analogRead(2) / 10; // potenziometri di regolazione
  kI = analogRead(3) / 10;
  P = orientation / kP;
  I = I + (P * cycleTime) / kI;
  PID = P + I;
  if(PID >= 90) PID = 90;
  if(PID <= -90) PID = -90;
  left.write(90 + PID);
  right.write(90 - PID);
}

void loop() { 
  getOrientation();
  Serial.print(PID);
  Serial.print(" ");
  Serial.println(orientation);
} 
 

Gioblu Robotics © 2010 - 2012 · Sitemap · privacy

gioscarab@gmail.com · Via Savona 123 20146 Milano MI · PI 06977550968 · Codice fiscale MTLGNN86S09F205F

Gioblu BOTServer è online dal 10 Aprile 2010 - 319.232 Visite - 1.027.175 Pagine visualizzate - 182.309 Visitatori unici - 536 utenti attivi