1 Panoramica del progetto
Mimic è il primo progetto Open Source che la DAM Bros rilascia con licenza Creative Commons BY-NC-SA per permettere a chiunque di catturare i movimenti del corpo utilizzando materiale di uso quotidiano e tecnologie semplici ed economiche. Questi dati digitalizzati possono essere utilizzati per controllare robot umanoidi, modelli di realtà virtuale ed interagire con sistemi complessi. Il controllo è stato realizzato su tre diverse board molto popolari tra i makers: Arduino Uno, Arduino Mega e la STM32 NucleoF401RE.
1.1 Principio di funzionamento del sistema
Un esoscheletro equipaggiato con una rete di potenziometri trasforma i movimenti degli arti superiori di chi lo indossa in variazioni di resistenza. Queste variazioni sono convertite in angoli su dei piani dello spazio ed inviati al mondo esterno tramite una connessione Bluetooth.
1.2 Interazione con il robot umanoide
Gli angoli generati dall’esoscheletro vengono utilizzati per far muovere un piccolo robot umanoide realizzato con dei servomotori posizionati in corrispondenza delle articolazioni di cui mima il movimento. Gli angoli ricevuti dalla connessione Bluetooth vengono utilizzati per modificare i segnali PWM di controllo dei servomotori del robot. In questo modo ogni servomotore segue le variazioni dell’angolo esattamente con la stessa ampiezza e la stessa velocità.
1.3 Interazione con un modello virtuale:
Gli angoli generati dall’esoscheletro possono essere utilizzati anche valorizzare le posizioni degli arti di un modello virtuale. Abbiamo effettuato un test di controllo su di un avatar virtuale sviluppato dai ragazzi del team Bytemotion con cui collaboriamo.
2 Circuito di controllo con la scheda NucleoF401RE
Il circuito di controllo dell’esoscheletro realizzato con la scheda Nucleo è attualmente quello con le caratteristiche più performanti, poichè è basato su un microcontrollore a 32bit (STM32) invece degli 8 bit disponibili nelle versioni controllate con Arduino. La NucleoF401RE ha lo stesso numero di ingressi ADC dell’Arduino Mega, ma un fattore di forma analogo a quello dell’Arduino Uno. La conversione AD della Nucleo è restituita su 12 bit invece che sui 10 bit di Arduino, con un aumento notevole della sensibilità di rilevamento.
La rete di potenziometri è alimentata a 3.3V, mentre la scheda Bluetooth è alimentata a 5V: entrambe le alimentazioni sono prelevate dai pin della Nucleo. I potenziometri impiegati sono di tipi lineare ed hanno un valore da 1Kohm; si possono impiegare anche quelli da 2.2KOhm, sconsigliamo invece potenziometri da 10Kohm poichè la corrente che circolerebbe in ogni ramo di misura con un potenzimetro sarebbe troppo piccola rispetto ad un eventuale disturbo, le letture risulterebbero instabili quindi il sistema risentirebbe troppo del rumore. Ciascun potenziometro ha 3 pin: quelli esterni si collegano rispettivamente all’alimentazione 3,3V e a massa, mentre quello centrale restituisce una tensione variabile tra 0V e 3,3V a seconda della rotazione dell’albero. Lo schema elettrico dei collegamenti della tuta è visibile nell’immagine seguente:
Clicca per scaricare i File Fritzing per Nucleo F401RE
2.1 I collegamenti dei PIN
- PA_0 = ADC1_IN0 = A0 – Potenziometro palmoDx
- PA_1 = ADC1_IN1 = A1 – Potenziometro palmoSx
- PA_2 = ADC1_IN2 = A2 – Potenziometro polsoDx
- PA_3 = ADC1_IN3 = A3 – Potenziometro polsoSx
- PA_4 = ADC1_IN4 = A4 – Potenziometro gomitoDx
- PA_5 = ADC1_IN5 = A5 – Potenziometro gomitoSx
- PA_6 = ADC1_IN6 = A6 – Potenziometro spallaDx
- PA_7 = ADC1_IN7 = A7 – Potenziometro spallaSx
- PB_0 = ADC1_IN8 = A8 – Potenziometro schienaDx
- PB_1 = ADC1_IN9 = A9 – Potenziometro schienaSx
- D8= RX Bluetooth
- D2= TX Bluetooth
2.2 Il firmware di controllo
Il codice di gestione della Nucleo è stato realizzato utilizzando l’IDE online MBED
Il firmware si compone di una parte iniziale dove vengono definiti gli angoli massimi rilevati, le assegnazioni dei PIN dei canali analogici e i prototipi delle funzioni utilizzate:
//Progetto MIMIC //Firmware per Esocheletro con scheda Nucleo F401RE //Autore: DAM Bros robotics //Licenza: Creative Commons BY-NC-SA #include "mbed.h" #define sample 100 // Numero di campioni per le medie //Definizione degli angoli massimi generati dalla tuta #define angolo_max_palmoDx 180 #define angolo_max_palmoSx 180 #define angolo_max_polsoDx 140 #define angolo_max_polsoSx 140 #define angolo_max_gomitoDx 160 #define angolo_max_gomitoSx 160 #define angolo_max_spallaDx 110 #define angolo_max_spallaSx 110 #define angolo_max_schienaDx 100 #define angolo_max_schienaSx 100
Il main inizia con la definizione delle variabili necessarie per la memorizzazione dei valori minimi e massimi delle letture dei potenziometri, per le letture delle tensioni istantanee e per gli angoli ricavati da queste ultime. Si definisce poi il baudrate della porta seriale utilizzata dal modulo Blueetooth HC-05.
int main(){ //Variabili per valorimi minimi dei potenziometri float min_pot1=0,min_pot2=0,min_pot3=0,min_pot4=0,min_pot5=0,min_pot6=0,min_pot7=0,min_pot8=0,min_pot9=0,min_pot10=0; //Variabili per valorimi massimi dei potenziometri float max_pot1=0,max_pot2=0,max_pot3=0,max_pot4=0,max_pot5=0,max_pot6=0,max_pot7=0,max_pot8=0,max_pot9=0,max_pot10=0; //Variabili per valorimi letti dai potenziometri float sens1,sens2,sens3,sens4,sens5,sens6, sens7,sens8,sens9,sens10; //Variabili per angoli mappati dalle letture float angolo_palmoDx, angolo_palmoSx, angolo_polsoDx, angolo_polsoSx, angolo_gomitoDx, angolo_gomitoSx, angolo_spallaDx, angolo_spallaSx, angolo_schienaDx, angolo_schienaSx; blutooth.baud(115200); //per HC-05_Master
Al settaggio della velocità del Bluetooth segue un ciclo di 5 lampeggi del led utente della scheda Nucleo per segnalare all’operatore che indossa l’esoscheletro di assumere la posizione di riposo iniziale. Dopo un’attesa di 5 secondi inizia poi un ciclo di 100 letture per il calcolo dei 10 valori minimi generati dai potenziometri della tuta.
//CALIBRAZIONE TUTA - CALCOLO VALORI MINIMI DEI POTENZIOMETRI //----------------------------------------------------------------------------------------- pc.printf("Inizio calcolo valori minimi\r\n"); // 5 Lampeggi del LED a bordo della Nucleo per segnalare l'avvio della fase 1 di calibrazione for(int i=0; i<5; i++) { led = 1; // LED is ON wait_ms(500); led = 0; // LED is OFF wait_ms(500); } wait(5); //Tempo di attesa prima del ciclo di letture dei minimi //----------------------------------------------------------------------------------------- //Lettura e accumulo dei valori minimi potenziometri - Tuta a riposo for(int n=0; n< sample; n++) { min_pot1 += pot1.read(); //Accumulo valori palmoDx min_pot2 += pot2.read(); //Accumulo valori palmoSx min_pot3 += pot3.read(); //Accumulo valori polsoDx min_pot4 += pot4.read(); //Accumulo valori polsoSx min_pot5 += pot5.read(); //Accumulo valori gomitoDx min_pot6 += pot6.read(); //Accumulo valori gomitoSx min_pot7 += pot7.read(); //Accumulo valori spallaDx min_pot8 += pot8.read(); //Accumulo valori spallaSx min_pot9 += pot9.read(); //Accumulo valori schienaDx min_pot10 += pot10.read(); //Accumulo valori schienaSx wait_ms(10); } //Media valori minimi min_pot1 /= sample; //Media valori minimi valori palmoDx min_pot2 /= sample; //Media valori minimi valori palmoSx min_pot3 /= sample; //Media valori minimi valori polsoDx min_pot4 /= sample; //Media valori minimi valori polsoSx min_pot5 /= sample; //Media valori minimi valori gomitoDx min_pot6 /= sample; //Media valori minimi valori gomitoSx min_pot7 /= sample; //Media valori minimi valori spallaDx min_pot8 /= sample; //Media valori minimi valori spallaSx min_pot9 /= sample; //Media valori minimi valori schienaDx min_pot10 /= sample; //Media valori minimi valori schienaSx wait_ms(10); //-----------------------------------------------------------------------------------------
Segue un secondo ciclo di 5 lampeggi del led utente della scheda Nucleo per segnalare all’operatore che indossa l’esoscheletro di assumere la posizione massima permessa dai giunti della tuta. Dopo un’attesa di altri 5 secondi inizia un ciclo di 100 letture per il calcolo dei 10 valori massimi generati dai potenziometri della tuta.
//CALIBRAZIONE TUTA - CALCOLO VALORI MINIMI DEI POTENZIOMETRI //----------------------------------------------------------------------------------------- // 5 Lampeggi del LED a bordo della Nucleo per segnalare l'avvio della fase di calibrazione for(int i=0; i<5; i++) { led = 1; // LED is ON wait_ms(500); led = 0; // LED is OFF wait_ms(500); } wait(5); //Tempo di attesa prima del ciclo di letture dei massimi //----------------------------------------------------------------------------------------- //Lettura e accumulo dei valori massimi potenziometri - Tuta a riposo for(int n=0; n< sample; n++) { max_pot1 += pot1.read(); //Accumulo valori palmoDx max_pot2 += pot2.read(); //Accumulo valori palmoSx max_pot3 += pot3.read(); //Accumulo valori polsoDx max_pot4 += pot4.read(); //Accumulo valori polsoSx max_pot5 += pot5.read(); //Accumulo valori gomitoDx max_pot6 += pot6.read(); //Accumulo valori gomitoSx max_pot7 += pot7.read(); //Accumulo valori spallaDx max_pot8 += pot8.read(); //Accumulo valori spallaSx max_pot9 += pot9.read(); //Accumulo valori schienaDx max_pot10 += pot10.read(); //Accumulo valori schienaSx wait_ms(10); } //Media valori minimi max_pot1 /= sample; //Media valori massimi valori palmoDx max_pot2 /= sample; //Media valori massimi valori palmoSx max_pot3 /= sample; //Media valori massimi valori polsoDx max_pot4 /= sample; //Media valori massimi valori polsoSx max_pot5 /= sample; //Media valori massimi valori gomitoDx max_pot6 /= sample; //Media valori massimi valori gomitoSx max_pot7 /= sample; //Media valori massimi valori spallaDx max_pot8 /= sample; //Media valori massimi valori spallaSx max_pot9 /= sample; //Media valori massimi valori schienaDx max_pot10 /= sample; //Media valori massimi valori schienaSx wait_ms(10); //-----------------------------------------------------------------------------------------
Dopo la calibrazione si ha un ultimo ciclo di 5 lampeggi del led utente per segnalare all’operatore che la fase di taratura iniziale della tuta è terminata. Dopo un’attesa di altri 5 secondi si entra in un ciclo infinito che provvede a leggere i valori dei 10 ADC collegati ai potenziometri dei giunti e a convertitli in angoli.
//----------------------------------------------------------------------------------------- // 5 Lampeggi del LED a bordo della Nucleo per segnalare l'avvio della fase di calibrazione for(int i=0; i<10; i++) { led = 1; // LED is ON wait_ms(500); led = 0; // LED is OFF wait_ms(150); } wait(5); //Tempo di attesa prima del ciclo di letture dei massimi //----------------------------------------------------------------------------------------- //LETTURA VALORI POTENZIOMETRI E CONVERSIONE IN ANGOLI (Utilizzo della funzione map) //----------------------------------------------------------------------------------------- while(1) { //Lettura potenziometro 1 - palmoDx sens1 = pot1.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_palmoDx = map(sens1,min_pot1,max_pot1,0,angolo_max_palmoDx); //Lettura potenziometro 2 - palmoSx sens2 = pot2.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_palmoSx= map(sens2,min_pot2,max_pot2,0,angolo_max_palmoSx); //Lettura potenziometro 3 - polsoDx sens3 = pot3.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_polsoDx = map(sens3,min_pot3,max_pot3,0,angolo_max_polsoDx); //Lettura potenziometro 4 - polsoSx sens4 = pot4.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_polsoSx = map(sens4,min_pot4,max_pot4,0,angolo_max_polsoSx); //Lettura potenziometro 5 - gomitoDx sens5 = pot5.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_gomitoDx = map(sens5,min_pot5,max_pot5,0,angolo_max_gomitoDx); //Lettura potenziometro 6 - gomitoSx sens6 = pot6.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_gomitoSx = map(sens6,min_pot6,max_pot6,0,angolo_max_gomitoSx); //Lettura potenziometro 7 - spallaDx sens7 = pot7.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_spallaDx = map(sens7,min_pot7,max_pot7,0,angolo_max_spallaDx); //Lettura potenziometro 8 - spallaSx sens8 = pot8.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_spallaSx = map(sens8,min_pot8,max_pot8,0,angolo_max_spallaSx); //Lettura potenziometro 9 - schienaDx sens9 = pot9.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_schienaDx = map(sens9,min_pot9,max_pot9,0,angolo_max_schienaDx); //Lettura potenziometro 10 - schienaSx sens10 = pot10.read(); // Legge e converte in gradi il valore di ingresso analogico angolo_schienaSx = map(sens10,min_pot10,max_pot10,0,angolo_max_schienaSx);
Dopo il ciclo di letture e il mapping dei valori degli ADC si inviano gli angoli generati sulle seriali collegate al Bluetooth e alla porta USB, tramite due semplici printf. Ogni stringa di dati inizia con il carattere di intestazione #, termina con il carattere di chiusura | e i dati sono separati dal carattere ;
//Stampa valori dei potenziometri convertiti in angoli pc.printf("#%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f|\r\n",angolo_palmoDx,angolo_palmoSx,angolo_polsoDx,angolo_polsoSx,angolo_gomitoDx,angolo_gomitoSx,angolo_spallaDx,angolo_spallaSx,angolo_schienaDx,angolo_schienaSx); bluetooth.printf("#%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f;%3.0f|\r\n",angolo_palmoDx,angolo_palmoSx,angolo_polsoDx,angolo_polsoSx,angolo_gomitoDx,angolo_gomitoSx,angolo_spallaDx,angolo_spallaSx,angolo_schienaDx,angolo_schienaSx); wait_ms(10); // 10 ms } }
Fuori dal main il programma si chiude con il corpo della funzione map che converte un valore di ingresso compreso in un certo range iniziale, in un valore ad esso corrispondente in un certo range finale:
float map(float x,float in_min,float in_max,float out_min,float out_max) { float angolo_temp; angolo_temp =((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min) ; if (angolo_temp < out_min) {return out_min; } else if (angolo_temp > out_max) {return out_max; } else {return angolo_temp;} }
Codice Esoscheletro Nucleo F401RE
3 Circuito di controllo con Arduino MEGA
Il circuito di controllo dell’esoscheletro realizzato con la scheda Arduino MEGA ha lo stesso numero di ingressi ADC della scheda Nucleo, ma un fattore di forma maggiore rispetto ad essa. La conversione AD della MEGA è restituita su 10 bit invece che sui 12 bit della Nucleo, quindi con una minore sensibilità di rilevamento.
La distribuzione delle alimentazioni è analoga allo schema utilizzato per la Nucleo: la rete di potenziometri è alimentata a 3,3V, mentre la scheda Bluetooth è alimentata a 5V: entrambe le alimentazioni sono prelevate dai pin della MEGA. Lo schema elettrico dei collegamenti della tuta è visibile nell’immagine seguente.
Clicca per scaricare i File Fritzing per Arduino Mega
3.1 I collegamenti dei PIN
- A0 – Potenziometro palmoDx
- A1 – Potenziometro palmoSx
- A2 – Potenziometro polsoDx
- A3 – Potenziometro polsoSx
- A4 – Potenziometro gomitoDx
- A5 – Potenziometro gomitoSx
- A6 – Potenziometro spallaDx
- A7 – Potenziometro spallaSx
- A8 – Potenziometro schienaDx
- A9 – Potenziometro schienaSx
- D16 = RX Bluetooth
- D17 = TX Bluetooth
3.2 Il firmware di controllo
Il codice di gestione della MEGA è stato realizzato utilizzando l’IDE Arduino
Il firmware per l’Arduino Mega segue la stessa struttura del codice utilizzato per la Nucleo, ma è ripartito tra le funzione Setup e Loop. Nella parte iniziale vengono definiti gli angoli massimi rilevati e le assegnazioni dei PIN dei canali analogici:
//Progetto MIMIC //Firmware per Esocheletro con scheda Arduino MEGA //Autore: DAM Bros robotics //Licenza: Creative Commons BY-NC-SA #define sample 100 // Numero di campioni per le medie #define led 13 // LED on board connesso al pin 13 //Definizione degli angoli massimi generati dalla tuta #define angolo_max_palmoDx 180 #define angolo_max_palmoSx 180 #define angolo_max_polsoDx 140 #define angolo_max_polsoSx 140 #define angolo_max_gomitoDx 160 #define angolo_max_gomitoSx 160 #define angolo_max_spallaDx 110 #define angolo_max_spallaSx 110 #define angolo_max_schienaDx 100 #define angolo_max_schienaSx 100 //Definisce i pin a cui sono collegati i potenziometri di sensing #define Palmo_Sx A0 #define Palmo_Dx A1 #define Polso_Sx A2 #define Polso_Dx A3 #define Gomito_Sx A4 #define Gomito_Dx A5 #define Spalla_Sx A6 #define Spalla_Dx A7 #define Schiena_Sx A8 #define Schiena_Dx A9
Prima del Setup sono definite le variabili necessarie per la memorizzazione dei valori minimi e massimi delle letture dei potenziometri, per le letture delle tensioni istantanee e per gli angoli ricavati da queste ultime.
//Variabili per valorimi minimi dei potenziometri float min_pot1=0,min_pot2=0,min_pot3=0,min_pot4=0,min_pot5=0,min_pot6=0,min_pot7=0,min_pot8=0,min_pot9=0,min_pot10=0; //Variabili per valorimi massimi dei potenziometri float max_pot1=0,max_pot2=0,max_pot3=0,max_pot4=0,max_pot5=0,max_pot6=0,max_pot7=0,max_pot8=0,max_pot9=0,max_pot10=0; //Variabili per valorimi letti dai potenziometri float sens1,sens2,sens3,sens4,sens5,sens6, sens7,sens8,sens9,sens10; //Variabili per angoli mappati dalle letture float angolo_palmoDx, angolo_palmoSx, angolo_polsoDx, angolo_polsoSx, angolo_gomitoDx, angolo_gomitoSx, angolo_spallaDx, angolo_spallaSx, angolo_schienaDx, angolo_schienaSx;
In testa alla funzione Setup, che è eseguita all’accensione della scheda o alla pressione del Reset, si definiscono i baudrate delle porte seriali utilizzate dal modulo Blueetooth HC-05 e dalla USB. Segue poi un ciclo di 5 lampeggi del led sulla porta 13 per segnalare all’operatore che indossa l’esoscheletro di assumere la posizione di riposo iniziale. Dopo un’attesa di 5 secondi inizia poi un ciclo di 100 letture per il calcolo dei 10 valori minimi generati dai potenziometri della tuta.
void setup() { Serial.begin(115200); //per monitor seriale Serial2.begin(115200); //per modulo Bluetooh HC-06_Master pinMode(led, OUTPUT); //----------------------------------------------------------------------------------------- //CALIBRAZIONE TUTA - CALCOLO VALORI MINIMI E MASSIMI DEI POTENZIOMETRI //----------------------------------------------------------------------------------------- Serial.println("Inizio calibrazione valori minimi"); // 5 Lampeggi del LED a bordo della Nucleo per segnalare l'avvio della fase 1 di calibrazione for(int i=0; i<5; i++) { digitalWrite(led, HIGH); // LED is ON delay(500); digitalWrite(led, LOW);; // LED is OFF delay(500); } delay(5000); //Tempo di attesa prima del ciclo di letture dei minimi //----------------------------------------------------------------------------------------- //Lettura e accumulo dei valori minimi potenziometri - Tuta a riposo for(int n=0; n< sample; n++) { min_pot1 += analogRead(Palmo_Dx); //Accumulo valori palmoDx min_pot2 += analogRead(Palmo_Sx); //Accumulo valori palmoSx min_pot3 += analogRead(Polso_Dx); //Accumulo valori polsoDx min_pot4 += analogRead(Polso_Sx); //Accumulo valori polsoSx min_pot5 += analogRead(Gomito_Dx); //Accumulo valori gomitoDx min_pot6 += analogRead(Gomito_Sx); //Accumulo valori gomitoSx min_pot7 += analogRead(Spalla_Dx); //Accumulo valori spallaDx min_pot8 += analogRead(Spalla_Sx); //Accumulo valori spallaSx min_pot9 += analogRead(Schiena_Dx); //Accumulo valori schienaDx min_pot10 += analogRead(Schiena_Sx); //Accumulo valori schienaSx delay(10); } //Media valori minimi min_pot1 /= sample; //Media valori minimi valori palmoDx min_pot2 /= sample; //Media valori minimi valori palmoSx min_pot3 /= sample; //Media valori minimi valori polsoDx min_pot4 /= sample; //Media valori minimi valori polsoSx min_pot5 /= sample; //Media valori minimi valori gomitoDx min_pot6 /= sample; //Media valori minimi valori gomitoSx min_pot7 /= sample; //Media valori minimi valori spallaDx min_pot8 /= sample; //Media valori minimi valori spallaSx min_pot9 /= sample; //Media valori minimi valori schienaDx min_pot10 /= sample; //Media valori minimi valori schienaSx delay(10); //-----------------------------------------------------------------------------------------
Segue un secondo ciclo di 5 lampeggi del led per segnalare all’operatore che indossa l’esoscheletro di assumere la posizione massima permessa dai giunti della tuta. Dopo un’attesa di altri 5 secondi inizia un ciclo di 100 letture per il calcolo dei 10 valori massimi generati dai potenziometri della tuta.
// 5 Lampeggi del LED a bordo della Nucleo per segnalare l'avvio della fase di calibrazione Serial.println("Inizio calibrazione valori massimi"); for(int i=0; i<5; i++) { digitalWrite(led, HIGH); // LED is ON delay(500); digitalWrite(led, LOW);; // LED is OFF delay(500); } delay(5000); //Tempo di attesa prima del ciclo di letture dei massimi //----------------------------------------------------------------------------------------- //Lettura e accumulo dei valori massimi potenziometri - Tuta a riposo for(int n=0; n< sample; n++) { max_pot1 += analogRead(Palmo_Dx); //Accumulo valori palmoDx max_pot2 += analogRead(Palmo_Sx); //Accumulo valori palmoSx max_pot3 += analogRead(Polso_Dx); //Accumulo valori polsoDx max_pot4 += analogRead(Polso_Sx); //Accumulo valori polsoSx max_pot5 += analogRead(Gomito_Dx); //Accumulo valori gomitoDx max_pot6 += analogRead(Gomito_Sx); //Accumulo valori gomitoSx max_pot7 += analogRead(Spalla_Dx); //Accumulo valori spallaDx max_pot8 += analogRead(Spalla_Sx); //Accumulo valori spallaSx max_pot9 += analogRead(Schiena_Dx); //Accumulo valori schienaDx max_pot10 += analogRead(Schiena_Sx); //Accumulo valori schienaSx delay(10); } //Media valori massimi max_pot1 /= sample; //Media valori massimi valori palmoDx max_pot2 /= sample; //Media valori massimi valori palmoSx max_pot3 /= sample; //Media valori massimi valori polsoDx max_pot4 /= sample; //Media valori massimi valori polsoSx max_pot5 /= sample; //Media valori massimi valori gomitoDx max_pot6 /= sample; //Media valori massimi valori gomitoSx max_pot7 /= sample; //Media valori massimi valori spallaDx max_pot8 /= sample; //Media valori massimi valori spallaSx max_pot9 /= sample; //Media valori massimi valori schienaDx max_pot10 /= sample; //Media valori massimi valori schienaSx delay(10); //-----------------------------------------------------------------------------------------
Dopo la calibrazione si ha un ultimo ciclo di 5 lampeggi del led utente per segnalare all’operatore che la fase di taratura iniziale della tuta è terminata. Dopo un’attesa di altri 5 secondi si termina la funzione di Setup e si passa alla funzione Loop, che ciclicamente legge i valori dei 10 ADC collegati ai potenziometri dei giunti e a convertitli in angoli.
//LETTURA VALORI POTENZIOMETRI E CONVERSIONE IN ANGOLI //----------------------------------------------------------------------------------------- void loop() { //Lettura potenziometro 1 - palmoDx sens1 = analogRead(Palmo_Dx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_palmoDx = map(sens1,min_pot1,max_pot1,0,angolo_max_palmoDx); //Lettura potenziometro 2 - palmoSx sens2 = analogRead(Palmo_Sx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_palmoSx= map(sens2,min_pot2,max_pot2,0,angolo_max_palmoSx); //Lettura potenziometro 3 - polsoDx sens3 = analogRead(Polso_Dx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_polsoDx = map(sens3,min_pot3,max_pot3,0,angolo_max_polsoDx); //Lettura potenziometro 4 - polsoSx sens4 = analogRead(Polso_Sx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_polsoSx = map(sens4,min_pot4,max_pot4,0,angolo_max_polsoSx); //Lettura potenziometro 5 - gomitoDx sens5 = analogRead(Gomito_Dx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_gomitoDx = map(sens5,min_pot5,max_pot5,0,angolo_max_gomitoDx); //Lettura potenziometro 6 - gomitoSx sens6 = analogRead(Gomito_Sx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_gomitoSx = map(sens6,min_pot6,max_pot6,0,angolo_max_gomitoSx); //Lettura potenziometro 7 - spallaDx sens7 = analogRead(Spalla_Dx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_spallaDx = map(sens7,min_pot7,max_pot7,0,angolo_max_spallaDx); //Lettura potenziometro 8 - spallaSx sens8 = analogRead(Spalla_Sx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_spallaSx = map(sens8,min_pot8,max_pot8,0,angolo_max_spallaSx); //Lettura potenziometro 9 - schienaDx sens9 = analogRead(Schiena_Dx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_schienaDx = map(sens9,min_pot9,max_pot9,0,angolo_max_schienaDx); //Lettura potenziometro 10 - schienaSx sens10 = analogRead(Schiena_Sx); // Converts and read the analog input value (value from 0.0 to 1.0) angolo_schienaSx = map(sens10,min_pot10,max_pot10,0,angolo_max_schienaSx);
Dopo il ciclo di letture e il mapping dei valori degli ADC si inviano gli angoli generati sulle seriali collegate al Bluetooth e alla porta USB. La stringa di dati da inviare è identica a quella generata dalla Nucleo e si costruisce tramite una sequenza di Serial.print:
//Stampa valori dei potenziometri convertiti in angoli //Stampa su monitor seriale per Debug Serial.print("#"); Serial.print(angolo_palmoDx); Serial.print(";"); Serial.print(angolo_palmoSx); Serial.print(";"); Serial.print(angolo_polsoDx); Serial.print(";"); Serial.print(angolo_polsoSx); Serial.print(";"); Serial.print(angolo_gomitoDx); Serial.print(";"); Serial.print(angolo_gomitoSx); Serial.print(";"); Serial.print(angolo_spallaDx); Serial.print(";"); Serial.print(angolo_spallaSx); Serial.print(";"); Serial.print(angolo_schienaDx); Serial.print(";"); Serial.print(angolo_schienaSx); Serial.println("|"); delay(10); // 10 ms //Stampa su modulo Bluetooth per trasmissione dati Serial2.print("#"); Serial2.print(angolo_palmoDx); Serial2.print(";"); Serial2.print(angolo_palmoSx); Serial2.print(";"); Serial2.print(angolo_polsoDx); Serial2.print(";"); Serial2.print(angolo_polsoSx); Serial2.print(";"); Serial2.print(angolo_gomitoDx); Serial2.print(";"); Serial2.print(angolo_gomitoSx); Serial2.print(";"); Serial2.print(angolo_spallaDx); Serial2.print(";"); Serial2.print(angolo_spallaSx); Serial2.print(";"); Serial2.print(angolo_schienaDx); Serial2.print(";"); Serial2.print(angolo_schienaSx); Serial2.println("|"); delay(10); // 10 ms }
4 Circuito di controllo con Arduino UNO
Il circuito di controllo dell’esoscheletro realizzato con la scheda Arduino UNO ha una diversa gestione delle conversioni AD. Poichè il numero di ingressi ADC della UNO è inferiore rispetto a quelle della MEGA e della Nucleo ricorriamo a due convertitori AD esterni (un convertitore MCP3208 per ciascun lato dell’esoscheletro), che comunicano con la UNO tramite il bus SPI. La conversione AD realizzata dai due MCP3208 è restituita su 12 bit come per la Nucleo.
La distribuzione delle alimentazioni è analoga allo schema utilizzato per la MEGA: la rete di potenziometri è alimentata a 3,3V, mentre la scheda Bluetooth è alimentata a 5V. I due ADC esterni utilizzano sia l’alimentazione a 5V che quella da 3,3V. Poichè la Arduino UNO dispone di una sola porta seriale, per la comunicazione Bluetooth è necessario utilizzare una porta seriale virtuale, che implementiamo grazie alla libreria Software Serial sui pin D2 e D3. Lo schema elettrico dei collegamenti della tuta è visibile nell’immagine seguente.
Clicca per scaricare i File Fritzing per Arduino Uno
4.1 I collegamenti dei PIN
- 1 MCP3208 Dx(canale 0)-Potenziometro palmoDx
- 2 MCP3208 Dx(canale 1)-Potenziometro polsoDx
- 3 MCP3208 Dx(canale 2)-Potenziometro gomitoDx
- 4 MCP3208 Dx(canale 3)-Potenziometro spallaDx
- 5 MCP3208 Dx(canale 4)-Potenziometro schienaDx
- 1 MCP3208 Sx(canale 0)-Potenziometro palmoSx
- 2 MCP3208 Sx(canale 1)-Potenziometro polsoSx
- 3 MCP3208 Sx(canale 2)-Potenziometro gomitoSx
- 4 MCP3208 Sx(canale 3)-Potenziometro spallaSx
- 5 MCP3208 Sx(canale 4)-Potenziometro schienaSx
- 9 MCP3208 (DGND) – GND Arduino
- 10 MCP3208 (CS ) – D10
- 11 MCP3208 (Din ) – D11 (MOSI)
- 12 MCP3208 (Dout) – D12 (MISO)
- 13 MCP3208 (CLC ) – D13 (Clock)
- 14 MCP3208 (AGN ) – GND Arduino
- 15 MCP3208 (Vref) – 3,3V Arduino
- 16 MCP3208 (Vdd ) – 5V Arduino
- D3- RX Bluetooth
- D2- TX Bluetooth
4.2 Il firmware di controllo
Anche il codice di gestione della UNO è stato realizzato utilizzando l’IDE Arduino
Il firmware segue la struttura del codice utilizzato per la Nucleo e per la MEGA: si compone di una parte iniziale dove vengono definiti gli angoli massimi rilevati, le assegnazioni dei PIN dei canali analogici e i prototipi delle funzioni utilizzate.
La differenza sostanziale si ha nella parte di acquisizione delle letture analogiche dei potenziometri, che l’Arduino UNO legge dal bus SPI.
5 Le altre componenti dell’Esoscheletro
La struttura meccanica dell’esoscheletro è costituita da due componenti principali:
- I giunti stampati in 3D, che fungono da articolazioni per la struttura.
- I link tra i vari giunti della struttura che nel loro insieme realizzano la struttura indossabile
5.1 I giunti da stampare in 3D
Le articolazioni dell’esoscheletro sono state progettate per essere stampate in 3D, mentre per i giunti di collegamento si possono utilizzare dei tubi in PVC per canaline elettriche. Le varie parti da stampare, visibili nella galleria seguente, sono disponibili sul nostro profilo Thingiverse.
5.2 I link di connessione tra i giunti
Il link di collegamentro tra le varie articolazioni dell’esoscheletro sono realizzati con dei tubolari in PVC di diametro esterno da 16mm e spessore di 2 mm, facilmente reperibili nei negozi di ferramenta.
Le dimensioni dei link di connessione tra i vari giunti sono al momento realizzate su misura sul corpo di un membro del Team che abbiamo scelto a modello. Tuttavia stiamo realizzando una modifica che permette la regolazione dei vari link, così da permettere di indossare la tuta a persone con corporature diverse.