Mimic Project – Motion capture Open Source per il controllo remoto dei robot e della Realtà virtuale

3

Banner progetto mimic

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.

20161012_184603

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:

Collegamenti tra i componenti del circuito di Sensing e Trasmissione dell'Esoscheletro.

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.

 

tubo_rigido

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.

 

 

 

 

Share This:

The following two tabs change content below.
Mauro D'Ambrosi

Mauro D'Ambrosi

HARDWARE AND FIRMWARE ELECTRONIC DESIGNER Ingegnere Elettronico da sempre appassionato di robotica ed automazione. Si occupa di ricerca e sviluppo elettronico e realizza sistemi embedded. Tiene interventi in eventi a tema tecnologico e scrive articoli divulgativi. Gli piace capire come funzionano le cose...per questo spesso le smonta!

3 comments to Mimic Project – Motion capture Open Source per il controllo remoto dei robot e della Realtà virtuale

  • Tam1

    Ciao da un po’ lavoro ad un progetto per un esoscheletro a basso costo mi farebbe piacere avere un suo parere sul mio progetto

    Reply
    • Mauro D'Ambrosi
      Mauro D'Ambrosi

      Ciao, certamente. Puoi inviarci i dettagli del tuo progetto alla casella email: dam.bros.robotics@gmail.com
      Ti risponderemo appena possibile.

      Reply
      • Tam1

        ciao avete avuto modo di darci un occhiata?

        Reply

Lascia un commento

Comment
Name*
Mail*
Website*