Ardubottino

Da raspibo.
Jump to navigation Jump to search

Ardubottino è stato creato soprattutto per testare tre componenti: l'Arduino, il sensore della distanza a ultrasuoni e il ponte ad H. Lo chassis e i motori sono Tamiya.

Ardubottino.jpg

Componenti

Ardubottino ha questi componenti:

  • Arduino UNO [1]
  • Sensore di distanza a ultrasuoni SRF05 [2]
  • Il board con montato il ponte ad H L298 [3]
  • Kit Tamiya per lo chassis e i motori
  • Batteria da 9v

Il sensore di distanza è sprovvisto di pin, occorre quindi saldarne una strip prima di procedere.

Il sensore di distanza a ultrasuoni SRF05

102 1298.JPG

È piuttosto semplice da usare. Seguendo le istruzioni [ http://www.robot-electronics.co.uk/htm/srf05tech.htm trovate qui] si può notare che ha due modalità di comunicazioni, date dal pin Mode. Se questo pin è collegato alla 0v il sensore userà un solo pin per la comunicazione dei dati dell'eco (Echo) e la ricezione dei comandi (Trigger), se, al contrario, non è connesso a niente allora saranno usati due pin diversi. Nel caso dell'Ardubottino ho preferito usare la prima modalità, quella con un pin solo (soprattutto per pigrizia: perché è già così lo sketch di esempio "ping" nella libreria di Arduino!). Oltre al pin Mode e al pin Trigger/Echo occorre collegare il primo e l'ultimo pin rispettivamente a +5v e a terra. Nella foto si può vedere, da sinistra: +5v, non usato, Trigger/Echo (collegato al pin 13 di Arduino), Mode (terra), Terra (terra).

Il board ponte ad H L298

Ardubottino dettagliol298.jpg

Il ponte ad H L298 è utilissimo per manovrare due motori indipendenti. Può essere usato anche per muovere un motore passo-passo. Ha due ingressi per la corrente: tramite un ponticello può essere separata fra corrente per la logica e corrente per i motori. La logica dev'essere alimentata da +5v; se l'alimentazione è separata, i motori possono ricevere fino a +12v. Per comodità (e anche dopo diversi goffi tentativi per capire come funzionava) ho preferito alimentare i motori solo con i 5v.

Sui lati ci sono le connessioni per i motori mentre, a fianco dell'alimentazione, ci sono i pin che servono per comandarli. I pin sono sei, due sono gli enable per i motori e quattro servono per dare la direzione, due per motore. I pin dell'enable si possono chiudere con dei ponticelli, comandarli da Arduino/Raspberry Pi oppure gli si può mandare un impulso PWM per regolare la velocità.

Motori ad encoder, gioie (poche) e dolorer (tanto)

Il problema di Ardubottino è che non va dritto. Il motivo? Forse il ponte ad H non dà gli stessi voltaggi ai motori, forse i motori sono un po' diversi, forse si stanno usurando in modo diverso, forse i cingoli hanno qualche imperfezione, forse le ruote sono storte, forse è sbilanciato. Ad ogni modo ognuno di questi problemi (tranne le ruote storte e le imperfezioni dei cingoli) si sarebbero risolti scoprendo a che velocità vanno i motori. Per scoprire questo dato sono necessari gli encoder. Un encoder è una rotellina con dei fori e un sensore o due, composti da un LED e da un ricevitore a infrarossi, che sentono quando un foro è passato. Encoder di questo tipo si trovano ad esempio nelle rotelline dei mouse o in quelli che hanno ancora la pallina.

EncoderArdubottino.JPG

Ora: questi sarebbero degli encoder "fatti apposta" per il kit Tamiya. Uso il condizionale perché, se non sono stato io ad averli montati in modo approssimativo, il loro utilizzo è alquanto scomodo. Anzitutto la rotella non sta fissa sull'albero. Il foro esagonale è troppo grande e ha un notevole gioco. Il range del sensore è minimo e non tiene conto della struttura del kit Tamiya (la rotella va quasi a sfregare contro le viti che lo fissano allo chassis). Inoltre sono estremamente fragili: una delle rotelle si è spaccata subito in due. I sensori stessi, poi, non si incastrano nella sede e occorre incollarli. La lettura degli encoder andrebbe fatta sfruttando gli interrupt di Arduino. Gli interrupt sono dei pin che restano in ascolto e fanno scattare degli eventi quando cambiano valore[4]. Purtroppo uno dei due pin (sull'Arduino Uno sono il pin 2 e il pin 3) dava dei risultati estremamente inaffidabili. Dopo varie prove, il risultato migliore l'ho ottenuto usando la libreria Encoder [5] su due pin non di interrupt. Il risultato di tutta questa fatica è un robottino che grosso modo va dritto. Un risultato mediocre di molto inferiore alla calibrazione a occhio. Alla fine, infatti, ho preferito quest'ultima.

Lo sketch

Lo sketch deriva per una parte dall'esempio Ping già presente nella libreria di Arduino. In pratica fa avanzare Ardubottino fino a che non incontra un ostacolo. Se lo incontra sterza in un senso e poi nell'altro e alla fine prosegue per la direzione dove ha trovato più campo libero. 4 7 6 5 sono i pin a cui ho collegato il ponte ad H. Sterzo è il tempo che deve impiegare per sterzare. pinping è il pin a cui è attaccato il trigger/echo del sensore a ultrasuoni.

long duration;
long dursx;
long durdx;
const int sterzo = 400;
const int m1fd = 4;
const int m1bk = 7;
const int m2fd = 6;
const int m2bk = 5;
const int pinping = 13;
const int distanza = 500;

void setup() {
 pinMode(m1fd, OUTPUT);
 pinMode(m1bk, OUTPUT);
 pinMode(m2fd, OUTPUT);
 pinMode(m2bk, OUTPUT);
 dritto();
}

void loop() {
 if (echo() < distanza){
   ferma();
   sinistra();
   delay(sterzo);
   ferma();
   dursx = echo();
   destra();
   delay(sterzo*2);
   ferma();
   durdx = echo();
   if (dursx > durdx) {
     sinistra();
     delay(sterzo*2);
   }
 } else {
   dritto();
 }
}

void dritto() {
 digitalWrite(m1fd,HIGH);
 digitalWrite(m2fd,HIGH);
 digitalWrite(m1bk,LOW);
 digitalWrite(m2bk,LOW);
}

void destra() {
 digitalWrite(m1fd,LOW);
 digitalWrite(m2fd,HIGH);
 digitalWrite(m1bk,HIGH);
 digitalWrite(m2bk,LOW);
}

void sinistra() {
 digitalWrite(m1fd,HIGH);
 digitalWrite(m2fd,LOW);
 digitalWrite(m1bk,LOW);
 digitalWrite(m2bk,HIGH);
}

void ferma() {
 digitalWrite(m1fd,LOW);
 digitalWrite(m2fd,LOW);
 digitalWrite(m1bk,LOW);
 digitalWrite(m2bk,LOW);
 delay(500);
}

long echo() {
 pinMode(pinping, OUTPUT);
 digitalWrite(pinping, LOW);
 delayMicroseconds(2);
 digitalWrite(pinping, HIGH);
 delayMicroseconds(5);
 digitalWrite(pinping, LOW);
 pinMode(pinping, INPUT);
 duration = pulseIn(pinping,HIGH);
 return duration;
}