Arduino e stampa 3d: le nuove frontiere della robotica homemade
arduino e robotica in laboratorio -...
Transcript of arduino e robotica in laboratorio -...
hands on:
Fisiologia del nostro robot
Daniele Grosso(1)
1. Dipartimento di Fisica (Università di Genova)
arduino e robotica in laboratorio
Scuola Estiva Genova AIF-DIFI Piano Lauree Scientifiche, modulo di formazione insegnanti in laboratorio
Obbiettivi prendere confidenza con i sensori
esplorare le potenzialità del robot
comprendere come vengono acquisite le informazioni dai sensori e la loro natura fisica
verificare come leggere e trasmettere informazioni dal robot al PC
1. leggiamo la distanza da un ostacolo con il sensore ad ultrasuoni
2. leggiamo la distanza da un ostacolo con il sensore analogico ad infrarossi
3. Leggiamo la temperatura con LM35
4. sensori digitali ad infrarosso laterali e anticaduta
5. Controlliamo i motori
6. Controlliamo i servomotori
7. Rileviamo la velocità di rotazione con gli encoder
Traccia
Materiali arduino (per i test)
robot
oppure
robot con sensori connessi attraverso la protoshield
Sensore US il sensore tramite una delle due capsule
ultrasoniche, sparerà un treno di 8 impulsi di ultrasuoni
Gli impulsi rimbalzeranno sull'ostacolo più vicino e ritorneranno indietro per essere captati dall'altra capsula
Il circuito interno del sensore lo normalizzerà e lo elaborerà restituendoci un impulso squadrato e filtrato
Misurare tempi per misurare distanze la velocità del suono nell'aria è di circa 343m/s (corrispondenti a 0.0343 cm/us)
D(cm) = T(us) * 0.0343/2 = T(us) / 58.30
#define SONAR_TRIGGER_PIN 2
#define SONAR_ECHO_PIN 3
unsigned int measure_distance() {
// Trigger the SRF05:
digitalWrite(SONAR_TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(SONAR_TRIGGER_PIN, LOW);
// Wait for Echo Pulse
unsigned long pulse_length = pulseIn(SONAR_ECHO_PIN, HIGH);
// Convert Pulse to Distance
// pulse_length/58 = cm
return( (unsigned int) (pulse_length / 58) );
}
void setup() {
pinMode(SONAR_TRIGGER_PIN, OUTPUT);
pinMode(SONAR_ECHO_PIN, INPUT);
Serial.begin(9600);
}
void loop() {
unsigned int current_distance = measure_distance();
Serial.println(current_distance);
delay(125);
}
Sensore IR sharp
#define sensorIR float sensorValue, cm; void setup() { Serial.begin(9600); } void loop() { sensorValue = analogRead(sensorIR); cm = 10650.08 * pow(sensorValue,-0.935) - 10; // fit from data …. delay(100); Serial.println(cm); }
Dal datasheet o da misure !!!
Funzionamento del sensore IR Il sensore GP2Y0A02YK
lavora nel range 20-150cm
Il sensore genera un fascio IR (concentrato mediante una lente)
il fascio viene riflesso da un ostacolo e
insiste sul CCD del sensore
Misurando l’angolo di incidenza è possibile operare una triangolazione
Oltre 150cm non è più in grado di effettuare una triangolazione accurata, inoltre …
L’intensità della luce riflessa è molto bassa e il segnale sarebbe rumoroso
Temperatura con LM35
//declare variables float tempC; int tempPin = 0; void setup() { Serial.begin(9600); } void loop() { tempC = analogRead(tempPin);
//convert the analog data to temperature tempC = (5.0 * tempC * 100.0)/1024.0; Serial.print((byte)tempC);
//send the data to the computer delay(100);
}
Controllo motori int pwm_a = 3;
int pwm_b = 9;
int dir_a = 2;
int dir_b = 8;
void setup() {
pinMode(pwm_a, OUTPUT);
pinMode(pwm_b, OUTPUT);
pinMode(dir_a, OUTPUT);
pinMode(dir_b, OUTPUT);
analogWrite(pwm_a, 0);
analogWrite(pwm_b, 0);
}
void loop() {
digitalWrite(dir_a, LOW);
digitalWrite(dir_b, LOW);
delay(1000);
analogWrite(pwm_a, 128);
analogWrite(pwm_b, 128);
delay(1000);
digitalWrite(dir_a, HIGH);
digitalWrite(dir_b, HIGH);
delay(1000);
analogWrite(pwm_a, 128);
analogWrite(pwm_b, 128);
delay(1000);
}
• Prima di effettuare test assicurarsi che il robot sia su piattaforma (e che le ruote siano libere)
• Impostare la velocità a 0 nel setup • Decelerare e accelerare lentamente
Per un controllo accurato serve un feedback!
H bridge Problema: decidere il verso di rotazione di un motore avendo un solo generatore a disposizione
Soluzione: il circuito h bridge
COMBINAZIONE POLARITÀ EFFETTO
A & D avanti il motore gira
in avanti
B & C indietro il motore gira
all'indietro
A & B bloccato motore frenato
C & D bloccato motore frenato
Nessuna libero motore in
folle
A & C corto circuito
B & D corto circuito
Evitare come la peste !!! http://www.parallax.com/dl/docs/cols/nv/vol1/col/nv23.pdf
Controllo servomotori #include <Servo.h>
Servo myservo;
int pos = 0;
void setup() {
myservo.attach(9);
}
void loop() {
for(pos = 0; pos < 180; pos += 1) {
myservo.write(pos);
delay(15);
}
for(pos = 180; pos>=1; pos-=1) {
myservo.write(pos);
delay(15);
}
}
• 2 servo => 2 angoli (pan & tilt) • attendere che il servo
raggiunga la posizione prima di cambiarla
• fino a quando il servo è alimentato bloccato nella posizione impostata
encoder questa tecnica è basata sugli interrupt
utilizziamo il polling...?
Codice gray
#define LEFT 0 #define RIGHT 1 long coder[2] = {0,0}; int lastSpeed[2] = {0,0}; void setup(){ Serial.begin(9600); attachInterrupt(LEFT, LwheelSpeed, CHANGE); attachInterrupt(RIGHT, RwheelSpeed, CHANGE); } void loop(){ static unsigned long timer = 0; //print manager timer if(millis() - timer > 100) { Serial.print("Coder value: "); Serial.print(coder[LEFT]); Serial.print("[Left Wheel] "); Serial.print(coder[RIGHT]); Serial.println("[Right Wheel]"); lastSpeed[LEFT] = coder[LEFT]; lastSpeed[RIGHT] = coder[RIGHT]; coder[LEFT] = 0; //clear the data buffer coder[RIGHT] = 0; timer = millis(); } } void LwheelSpeed() { coder[LEFT] ++; } void RwheelSpeed() { coder[RIGHT] ++; }
Impacchettare più bit in un byte per rendere più efficiente la trasmissione
4 sensori digitali infrarosso anticollisione
2 sensori digitali infrarosso anticaduta
Un byte è più che sufficiente per 6 bit !!!
Funzioni arduino per la gestione di bit
bitRead
bitWrite
bitSet
bitClear
Sensori gas
int gasSensor = 0;
int val = 0; void setup() {
Serial.begin(9600);
}
void loop() {
val = analogRead(gasSensor);
Serial.println( val );
delay(100);
}
Un progetto interessante: monitorare fughe di gas con arduino
• A temperatura ambiente l'elemento sensibile presenta una resistenza elevatissima a causa dell'alta resistività del materiale
• A caldo (400 gradi), in presenza di un gas riducente, la resistività cambia...
Meccanica dual drive
• Per la stabilità servono almeno 3 punti di appoggio: 2 ruote indipendenti e ball caster • Il controllo proporzionale (oppure on-off) avviene mediante encoder
Dual drive: spostamento lineare Per misure di distanza percorsa e per stabilizzare la traiettoria occorre:
convertire la rotazione delle ruote in un movimento lineare
compensare la diversa velocità di rotazione dei motori
Dual drive: spostamento Dato il numero di impulsi registrati dall’encoder è possibile determinare il tratto percorso (…misure!)
Dual drive: orientamento La variazione di orientamento e quindi l’orientamednto del robot (rispetto all’istante iniziale in cui è stato attivato) si possono ottenere dalle relazioni:
Integrazione…
Odometria e determinazione della traiettoria errori casuali e sistematici, correzione con data fusion
Odometria:
valutare lo spostamento
sommare lo spostamento attuale al precedente per ottenere la traiettoria
Problema:
l’accumolo degli errori casuali
la presenza di errori sistematici
Tecnica di test:
programmare ilmovimento lungo il perimetro di un quadrato
effettuare misure per la calibrazione
Compensazione degli errori mediante la data fusion:
La traiettoria viene corretta con informazioni provenienti da fonti indipendenti; bussola, gps, triangolazione, mappe …
Triangolazione di landmark Landmark: punti di riferimento di posizione nota
Mediante triangolazione (o multilaterazione) si stima la posizione del robot relativamente ai landmark
Navigazione e mappe In alternativa e/o a complemento dei landmark si usano le mappe dell’ambiente (note a priori o costruite dinamicamente)
Si determina la propria posizione relativamente alla mappa e si aggiorna la mappa mentre si cerca di raggiungere un target …
Trasmissione BT Stabilire la connessione PC-seeduino via BT
Utilizzare la libreria software seriale per trasmettere le informazioni da seeduino a PC trasmettere un carattere da PC a seeduino per controllare il robot
Stabilire un protocollo asimmetrico EFFICIENTE !!
Controllo heartbeat: in assenza di comandi, dopo un certo tempo, può essere disattivato il robot (per sicurezza) oppure entrare in modalità autonoma …)
Xbee?
? ?
bluetooth?
radio?
wifi? TCP? UDP?
Telemetria e controllo remoto Il robot acquisisce dati sull’ambiente attraverso i sensori
Le informazioni sono trasmesse attraverso la connessione BT
Una apposita funzione del programma di controllo remoto del robot (ad es realizzato con processing),
rimane in ascolto sul canale seriale BT
legge i dati dei sensori (immessi in una stringa di testo tab delimited (oppure in una sequenza di byte di lunghezza prefissata)
estrae i dati di ciascun sensore e aggiorna un vettore di stato (che rappresenta lo stato interno del robot)
Una funzione del programma decide quali comandi inviare al robot (è sufficiente un carattere per 256 stati!) (1)
Una funzione invia i comandi al robot attraverso BT
BT
• definire un protocollo comune efficiente non è facile • imparare a parlare non è facile • insegnare una lingua non è facile … ci vuole tanta PAZIENZA !
Lato robot (arduino|seeduino…) #include <SoftwareSerial.h> //Software Serial Port
#define RxD 4
#define TxD 5
#define DEBUG_ENABLED 1
SoftwareSerial blueToothSerial(RxD,TxD);
char incoming;
char InternalStatus[50];
int dataBT=38400;
void setup() {
Serial.begin(9600);
pinMode(RxD, INPUT);
pinMode(TxD, OUTPUT);
setupBlueToothConnection();
}
void setupBlueToothConnection() {
blueToothSerial.begin(38400); //Set BluetoothBee BaudRate to default baud rate 38400
delay(1000);
sendBlueToothCommand("\r\n+STWMOD=0\r\n");
sendBlueToothCommand("\r\n+STNA=wally\r\n"); // CAMBIA IL NOME DEL TUO ROBOT
sendBlueToothCommand("\r\n+STAUTO=0\r\n");
sendBlueToothCommand("\r\n+STOAUT=1\r\n");
sendBlueToothCommand("\r\n +STPIN=0000\r\n");
delay(2000); // This delay is required.
sendBlueToothCommand("\r\n+INQ=1\r\n");
delay(2000); // This delay is required.
} //Checks if the response "OK" is received
void CheckOK() {
char a,b;
while(1) {
if(blueToothSerial.available()) {
a = blueToothSerial.read();
if('O' == a) {
// Wait for next character K. available() is required in some cases, as K is not immediately available.
while(blueToothSerial.available()) {
b = blueToothSerial.read();
break;
}
if('K' == b) {
break;
} } }
} while( (a = blueToothSerial.read()) != -1) {
//Wait until all other response chars are received
}
}
void sendBlueToothCommand(char command[]) { blueToothSerial.print(command); //CheckOK(); } void loop() { updateStatus(); blueToothSerial.println(InternalStatus); // get character incoming=blueToothSerial.read(); if (incoming!=-1) { Serial.println(incoming); // dump everything } // decide what to do with it switch (incoming) { case '1': Serial.println("[1]"); // insert here your code break; case '2': Serial.println("[2]"); // insert here your code break; case '3': Serial.println("[3]"); // insert here your code break; } delay(100); // may be removed } void updateStatus(void) { char status[16]; int A0=analogRead(A0); int A1=analogRead(A1); int A2=analogRead(A2); int A3=analogRead(A3); int A4=analogRead(A4); int A5=analogRead(A5); sprintf(InternalStatus, "%d\t%d\t%d\t%d\t%d\t%d\t\n ", A0, A1, A2, A3, A4, A5); }
Lato processing import processing.serial.*;
Serial myPort; // Create object from Serial class
int val; // Data received from the serial port
void setup() {
size(200, 200);
// List all the available serial ports
println(Serial.list());
String portName = Serial.list()[12];
myPort = new Serial(this, portName, 38400);
}
void draw() {
while (myPort.available() > 0) {
String inBuffer = myPort.readString();
if (inBuffer != null) {
println("BT: "+inBuffer); // dump everything
int [] nums;
String [] splits = split(inBuffer, "\t"); // split
nums = new int[splits.length]; // create a target array
for(int i = 0; i < splits.length; i++){
nums[i] = int(splits[i]);} // insert into numbers
print(" <"); // begin
for(int i = 0; i < splits.length; i++){
print(nums[i]+" "); // dump one by one
}
println(" >"); // end
}
}
}
• Perchè Processing possa utilizzare le seriali (USB, BT dopo il pairing) occorre:
• Identificare il numero ID assegnato alla porta • Associare una porta in serial list ad un oggetto specifico
(una istanza di Serial)
Gestire e monitorare la connessione Utilizzare: • terminal nell’ide di arduino
per monitorare la connessione USB • un emulatore terminale,
ad esempio X-CTU, uno strumento molto utile! (http://ftp1.digi.com/support/utilities/40002637_c.exe) per monitorare la connessione BT
Perdita di connessione? Il robot commuta su
stop
autonomo search and connect mode
Riferimenti utili: • http://www.westernwillow.com/cms/blog/franco/creating-bluetooth-serial-port-ubuntu • http://askubuntu.com/questions/2977/how-to-assign-a-serial-port-to-my-bluetooth-phone • http://scottada.ms/article/adding-so-called-virtual-bluetooth-serial-port-ubuntu-1110-using-
atheros-ar3011-based-usb • http://www.thinkwiki.org/wiki/How_to_setup_Bluetooth • http://www.broadcom.com/support/bluetooth/update.php • http://www.ladyada.net/make/xbee/configure.html