Mano robotica con Arduino – un progetto di Giuseppe

Settimana scorsa l’appassionato arduino e lettore del blog Giuseppe mi ha inviato una email con il suo progetto: una Mano robotica con aduino autocostruita.

mano robotica

Giuseppe mi ha anche inviato tutte le foto, la descrizione del progetto ed un filmato, che trovi in fondo all’articolo, oltre all’autorizzazione a pubblicare tutto il suo materiale con la volontà di condividere il suo progetto.

Il progetto Mano robotica con arduino è senza dubbio uno di quei progetti che un po’ tutti gli appassionati di elettronica , meccanica e robotica abbiamo provato a realizzare e senza dubbio con arduino questo progetto è realizzabile con un po’ di pratica e tanta voglia di fare.

Costruzione della parte mecanica della mano robotica

per la realizzazione della parte meccanica Giuseppe scrive:

La parte meccanica è presa da un tutorial sul sito emcelettronica, un semplice modo per costruire con materiali facilmente reperibili la struttura della mano. Possiamo aggiungere a questo progetto una barra metallica legata ad un cuscinetto rotante ed un supporto fisso, ottenendo la rotazione del polso.

effettivamente se osservi il progetto il materiale è facilmente reperibile:

  • qualche metro di tubo corrugato, dipende da quanto vuoi grande la mano;
  • del filo di naylon o simile;
  • colla a caldo;
  • n.6 servomotori;
  • una staffa fissa;
  • un asse metallico collegato alla staffa fissa;
  • un cuscinetto.

A questo materiale devi aggiunger la parte elettronica:

  • n.1 arduino uno o simili;
  • n.1 connettore autocostruito a 7 contatti da 3 pin ciascuno per collegare i servo;
  • n.1 nunchuck per pilotare la mano robotica
  • n.1 alimentatore da 6v 1,7A per alimentare i servo;
  • n.1 pila da 9v per alimentare Arduino.

Assemblare la parte meccanica della mano robotica

Per costruire la parte meccanica ti consiglio di seguire il tutorial che Giuseppe suggerisce perchè benfatto: Mano Robotica parte meccanica realizzata con il tubo corrugato, il filo di naylon e della colla a caldo.

Ecco una foto di un particolare della mano robotica realizzata:

montaggio servo mano robotica

Assemblare la parte elettrica della mano robotica

Per la parte elettrica hai bisogno di un saldatore che ti permetta di realizzare il connettore per i servo:

in pratica tutti i pin positivi sono saldati insieme tra loro e connessi al polo positivo dell’alimentatore a 6v 1,7A, così come tutti i pin negativi sono saldati insieme tra loro e collegati al polo negativo del medesimo alimentatore:

particolare del connettore servo

Passa al collegamento del nunchuk, puoi seguire il tutorial su questo blog, aquistando un connettore per pochi o  tagliare il connettore del nunchuk e collegare i cavi come descritto da Giuseppe:

collegamenti nunchuck mano robotica

Tagliando il connettore, colleghiamo il cavo bianco al pin GND, il cavo rosso all’alimentazione da 3,3 volt forniti dalla scheda del microcontrollore, il cavo giallo all’ingresso analogico A5 ed il cavo verde all’ingresso A4. (In foto il cavo nero è prolungamento del cavo bianco) 

in ogni caso l’importante è che i collegamenti siano fissi e che tu non abbia dei falsi contatti tra il nunchuck e arduino per evitare malfunzionamenti.

Lo sketch della mano robotica

Giuseppe ha realizzato lo sketch seguente come esempio di ciò che puoi realizzare:

#include <Wire.h>
#include <string.h>
#include <stdio.h>
#include <Servo.h>

uint8_t outbuf[6];

int cnt = 0;
int flag = 0;

int pulseWidth = 0;
int pulseWidth2 = 0;

long lastPulse = 0;
long lastPulse2 = 0;

int z_button = 0;
int c_button = 0;

int refreshTime = 20;

int minPulse = 1000;
int minPulse2 = 500;

int dtime=10;

    int joy_x_axis;
    int joy_y_axis;
    int accel_x_axis;
    int accel_y_axis;
    int accel_z_axis;

#define pwbuffsize 10
long pwbuff[pwbuffsize];
long pwbuffpos = 0;
long pwbuff2[pwbuffsize];
long pwbuffpos2 = 0;

//dichiarazione variabili servo

Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;
Servo servo6;

int val1;    // variabili per le posizioni dei servo
int val2;
int val3;
int val4;
int val5;
int val6;

void setup()
{
    servo1.attach(8);  // assegnazione piedini per i servo
    servo2.attach(9);
    servo3.attach(10);
    servo4.attach(11);
    servo5.attach(12);
    servo6.attach(13);

    Serial.begin (9600);
    Wire.begin ();
    nunchuck_init ();

    Serial.print ("Setup Completato\n");
}

void nunchuck_init()
{
    Wire.beginTransmission (0x52);
    Wire.write (0x40);
    Wire.write (0x00);
    Wire.endTransmission ();
}

void send_zero()
{
    Wire.beginTransmission (0x52);
    Wire.write (0x00);
    Wire.endTransmission ();
}

int t = 0;

void loop()
{
    t++;
    long last = millis();

    if( t == 1) {

        t = 0;

        Wire.requestFrom (0x52, 6);

        while (Wire.available ()) {
            outbuf[cnt] = nunchuk_decode_byte (Wire.read ());
            cnt++;
        }

        if (cnt >= 5) {

            int z_button = 0;
            int c_button = 0;

            if ((outbuf[5] >> 0) & 1)
                z_button = 1;
            if ((outbuf[5] >> 1) & 1)
                c_button = 1;
        }

        cnt = 0;
        send_zero();

    } // if(t==)

    joy_x_axis = outbuf[0];
    joy_y_axis = outbuf[1];
    accel_x_axis = outbuf[2]; // * 2 * 2;
    accel_y_axis = outbuf[3]; // * 2 * 2;
    accel_z_axis = outbuf[4]; // * 2 * 2;

    z_button = 0;
    c_button = 0;

    if ((outbuf[5] >> 0) & 1)
        z_button = 1;
    if ((outbuf[5] >> 1) & 1)
        c_button = 1;
    if ((outbuf[5] >> 2) & 1)
        accel_x_axis += 2;
    if ((outbuf[5] >> 3) & 1)
        accel_x_axis += 1;

    if ((outbuf[5] >> 4) & 1)
        accel_y_axis += 2;
    if ((outbuf[5] >> 5) & 1)
        accel_y_axis += 1;

    if ((outbuf[5] >> 6) & 1)
        accel_z_axis += 2;
    if ((outbuf[5] >> 7) & 1)
        accel_z_axis += 1;

 // interpretazione variabili nunchuck

 if(z_button==0)
      {if(flag==0) flag=1;
              else flag=0;
      }

 if((c_button==0)&&(z_button==1))
     if(flag==0){if(val5<180)val5+=20;}
            else{if(val5>19)val5-=20;}

 if((c_button==1)&&(z_button==1))
     if(flag==0){if(val5>19)val5-=20;}
            else{if(val5<180)val5+=20;}

 if((joy_y_axis > 220)||((joy_y_axis >= 0)&&(joy_y_axis < 40)))
    if(flag==0){if(val1<180) val1+=20;}
           else{if(val1>19)  val1-=20;}

 if((joy_y_axis > 45)&&(joy_y_axis < 160))
    if(flag==0){if(val3<180) val3+=20;}
           else{if(val3>19)  val3-=20;}

 if((joy_y_axis <171)&&(joy_y_axis > 167))
    if(flag==0){{if(val1>19) val1-=20;
                 if(val3>19) val3-=20;
                }
               }
          else {{if(val1<180) val1+=20;
                 if(val3<180) val3+=20;
                }
               } 

 if((joy_x_axis > 220)||((joy_x_axis >= 0)&&(joy_x_axis < 40)))
    if(flag==0){if(val2<180) val2+=20;}
           else{if(val2>19)  val2-=20;}

 if((joy_x_axis > 45)&&(joy_x_axis < 160))
    if(flag==0){if(val4<180) val4+=20;}
           else{if(val4>19)  val4-=20;}

 if((joy_x_axis <171)&&(joy_x_axis > 167))
    if(flag==0){{if(val2>19) val2-=20;
                 if(val4>19) val4-=20;
                }
               }
          else {{if(val2<180) val2+=20;
                 if(val4<180) val4+=20;
                }
               } 

 //controllo polso

 //val6=map(accel_x_axis, 63, 210, 0, 180);          alternativa poco pratica a causa
                                                                                    //dell'imprecisione del nunchuck di prova

 if(accel_x_axis<110)
    if(val6>19) val6-=20;

 if(accel_x_axis>150)
    if(val6<180) val6+=20;

    servo1.write(val1);                  // trasferimento del comando ai servo
    servo2.write(val2);
    servo3.write(val3);
    servo4.write(val4);
    servo5.write(val5);
    servo6.write(val6);

    printNunchuckData();
    delay(dtime);
}

int i=0;
void printNunchuckData()
{

    Serial.print (i,DEC);
    Serial.print ("\t");

    Serial.print ("X: ");
    Serial.print (joy_x_axis, DEC);
    Serial.print ("\t");

    Serial.print ("Y: ");
    Serial.print (joy_y_axis, DEC);
    Serial.print ("\t");

    Serial.print ("AccX: ");
    Serial.print (accel_x_axis, DEC);
    Serial.print ("\t");

    Serial.print ("AccY: ");
    Serial.print (accel_y_axis, DEC);
    Serial.print ("\t");

    Serial.print ("AccZ: ");
    Serial.print (accel_z_axis, DEC);
    Serial.print ("\t");

    Serial.print (z_button, DEC);
    Serial.print (" ");
    Serial.print (c_button, DEC);
    Serial.print ("\t");

    Serial.print (val1,DEC);
    Serial.print (" ");
    Serial.print (val2,DEC);
    Serial.print (" ");
    Serial.print (val3,DEC);
    Serial.print (" ");
    Serial.print (val4,DEC);
    Serial.print (" ");
    Serial.print (val5,DEC);
    Serial.print (" ");
    Serial.print (val6,DEC);
    Serial.print ("\t");
    Serial.print (flag,DEC);
    Serial.print ("\r\n");

    i++;
}

char nunchuk_decode_byte (char x)
{
    x = (x ^ 0x17) + 0x17;
    return x;
}

e nella documentazione inviatami riporta:

i movimenti vengono eseguiti per step crescenti o decrescenti invece di una mappatura diretta dell’accelerometro. Lo stesso metodo è stato usato per il joystick poiché in questo modo è possibile utilizzare le 4 direzioni per il controllo di 4 dita ed ottenere varie combinazioni di movimenti portando il cursore nelle posizioni intermedie. Queste posizioni sono utilizzabili poiché il movimento è attivato da uno spostamento abbastanza piccolo del cursore, quindi nelle posizioni intermedie le componenti x ed y del segnale ricevuto sono sufficienti ad innescare l’azione delle dita. Inoltre lo schetch prevede il ritorno alla posizione di “riposo” quando il joystick non viene toccato, quindi, evitando di passare dal centro, è possibile ottenere ulteriori movimenti arbitrari.

La posizione di “riposo “ , ovvero la decisione di far partire la mano con le dita aperte o chiuse, è modificabile tramite il tasto Z (secondo tasto grande); partendo dalla mano aperta e, muovendo il cursore, le dita si chiudono e premendo il tasto C (il primo tasto piccolo) si chiude il pollice. Se partiamo dalla mano chiusa abbiamo il movimento opposto.

In pratica i movimenti del joystick presente sul nunchuck muove le dita della mano robotiva mentre l’asse X dell’accellerometro simula la rotazione del poso se questo fosse connesso ad una struttura scheletrica simile a quello umano da cui tutta la mano robotica prende ispirazione.

Interessante l’uso del tasto “C” per il controllo del pollice opponibile di cui la mano è dotata e la funzione legata al tasto “Z” con cui puoi decidere se partire con la mano aperta o chiusa con un solo gesto.

Il video della mano robotica in azione

La mano robotica in movimento guidata da Giuseppe attraverso il nunchuck:

Buon divertimento !!!

Prima di inserire un commento, per favore, leggi il regolamento

Permanent link to this article: https://www.mauroalfieri.it/elettronica/mano-robotica-con-arduino.html

59 pings

Skip to comment form

  1. […] avrai letto questo articolo sulla mano robotica l’idea è simile, in collaborazione con Federico ho deciso di partecipare al progetto e di […]

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.