Arduino e Nunchuck – terza parte

Cosa puoi fare con un arduino, un nunchuck, due servomotori, del cartone e del nasto adesivo?

due occhi per arduino

Io mi sono divertito a realizzare una simpatica testa robot 🙂 è solo un esempio costruito con un poco tempo del cartone e del nastro adesivo, lo scopo vero di questo articolo è approfondire la comunicazione tra arduino e nunchuck e trasferire il movimento del joystick ai nostri occhietti.

Parti dalla meccanica della nostra testa, procurati una scatolina di cartone e su di un lato attacca un foglio di carta con disegnati i due occhi, sulla base blocca la squadretta del servo con del nastro adesivo:

testa per arduino

quindi passa a montare l’altra squadretta su uno dei server, anche in questo caso con del nastro adesivo:

montaggio della squadretta al servo

quindi monta tutto in modo che i due servo si trovino a 90° l’uno rispetto all’altro:

Montaggio dei due servo

ed infine monta la testa di cartone sul serve in alto:

due occhi per arduino

Prima di passare allo sketch vorrei sottolineare che provando 2 nunchuck i valori di base rilevati da arduino non coincidono perfetamente, per vedere i valori che rilevi sul tuo arduino ti consiglio di leggere il precedente articolo Arduino e Nunchuck – seconda parte.

Eseguendo lo sketch presentato in quell’articolo leggi i valori minimo e massimo sia per l’asse X sia per l’asse Y del joystick del nunchuck.

Il mio nunchuck mi ha fornito questi valori:

tabella

cioè il valore minimo è 26 e il valore massimo è 226 sia per l’asse X sia per l’asse Y.

Ed ecco lo sketch:

/*
 * Sketch Arduino, Nunchuck e servo motori
 *
 * @author: Alfieri Mauro
 * @see:    http://www.mauroalfieri.it
 *
 * @licenze: Creative common
 */

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

uint8_t outbuf[6];

int cnt = 0;

// Controllo Servo motori
int middle_gradX = 0;
int middle_gradY = 0;
int min_gradX = 20;
int min_gradY = 20;
int max_gradX = 160;
int max_gradY = 160;

int servoPinX = 5;
int servoPinY = 6;

Servo servoMotorX;
Servo servoMotorY;

// Nunchuck
int z_button = 0;
int c_button = 0;
int jx = 126;
int jy = 126;
int minX = 26;
int maxX = 226;
int minY = 26;
int maxY = 226;

int dtime=15;

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

void setup()
{
    Serial.begin (9600);
    Serial.println ("Inizio Setup");
    /** Servo **/
    servoMotorX.attach(servoPinX);
    servoMotorY.attach(servoPinY);

    middle_gradX = middleValue(min_gradX, max_gradX);
    middle_gradY = middleValue(min_gradY, max_gradY);

    servoMotorX.write(middle_gradX);
    servoMotorY.write(middle_gradY);

    /** Nunchuk **/
    Wire.begin ();
    nunchuck_init ();

    Serial.println ("Setup OK");
}

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

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

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

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 ());
            digitalWrite (ledPin, HIGH);
            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;

            if (c_button == 1) {
                jx = map(outbuf[0],maxX,minX,min_gradX,max_gradX);
                jy = map(outbuf[1],minY,maxY,min_gradY,max_gradY);
            }
        }
        cnt = 0;
        send_zero();

    } // if(t==)
    updateServo();
    delay(dtime);
}

void updateServo() {
    servoMotorX.write( jx );
    servoMotorY.write( jy );
}

int middleValue(int minV, int maxV)
{
  return (((maxV - minV)/2) + minV);
}

La maggior parte di questo sketch è uguale a quello del precedente articolo, la rilevazione del movimento del joystick del nunchuck avviene all’inetrno della funzione loop(), ci sono tuttavia delle importanti differenze:

linea 13: includi anche la libreria Servo.h che ti serve per far muovere i servo;

linee 19-25: definisci una serie di variabili di tipo integer con cui puoi stabilire i valori minimi e massimi di rotazione dei servo, questo tipo di settaggio è utile per adattare lo sketch facilmente al tuo progetto ed alla tipologia di servo che hai a disposizione, in particolare per ciascuno dei servo la variabile middle_grad è impostata a 0 e sarà calcolata in fase di setup, le variabili min_grad e max_grad servono a impostare il minimo ed il massimo punto in gradi di rotazione del servo, i servo comunemente utilizzati in modellismo sono del tipo 0-180°, per esigenze di progetto potresti aver bisogno di non utilizzare la massima escursione del server;

linee 27-28: impostano i pin a cui sono collegati i servomotori, al pin 5 collega il servo che si muove sull’asse X e al pin 6 quello che sposta l’asse Y, ricorda che i pin puoi cambiarli, ma è necessario che siano sempre di tipo PWM;

linee 30-31: definisci i due oggetti di tipo Servo a cui inviare i comendi di spostamento in gradi;

linee 33-41: definisci una serie di variabili di configurazione anche per i valori letti dal nunchuck, in particolare i valori min e max di ciascun asse sono gli stessi della tabella riportata sopra;

nella funzione setup() sono nuove le linee 55-63 in cui assegni i pin a cui sono connessi i servo ai rispettivi oggetti grazie al metodo attach(), calcoli il punto centrale in gradi di ciascun servo, per farlo ho usato la funzione middleValue() che trovi alla linea 135 e sposti il servo alla sua posizione media grazie al metodo write() della libreria Servo;

nella funzione loop() mi concentrerò sulle linee 188 e 119, utilizzando la funzione map() rimappa il valore minimo e massimo che potrai leggere sull’asse del joystick corrispondente sul valore minimo e massimo dei gradi che il servo può compiere; in questo modo ad ogni valore letto sull’asse X del joystick del nunchuk avrai un valore corrispondente in gradi da far eseguire al servo X, stessa condizione per il servo Y.

Un’ultima considerazione: avrai notato che i valori min e max per l’asse X sono invertiti, questo trucco ti permette di invertire il verso di rotazione, potresti non averne bisogno, dipende da come hai montato i servo tra loro.

Infine la linea 126 richiama per ogni ciclo la funzione updateServo() che si limita a posizionare il servo corrispondente alla posizione indicata, per farlo utilizza nuovamente il metodo write() dell’oggetto servo;

Il risultato è:

Buon divertimento.

Cortesemente, prima di inserire i commenti leggi il regolamento

Permanent link to this article: http://www.mauroalfieri.it/elettronica/arduino-e-nunchuck-terza-parte.html

24 comments

Skip to comment form

    • Gio on 11 giugno 2012 at 20:42
    • Reply

    Ciao
    scusa ma perchè non utilizzi il giroscopio ma solo il joystick?
    è possibile utilizzarlo o non si può?
    grazie mille per il tutorial!

    1. Ciao,
      in questo esempio ho voluto utilizzare il joystick, se cerchi nel blog troverai anche esempi in cui utilizzo tutti i sensori del nunchuk, anche l’accellerometro a 3 assi 🙂

      Mauro

  1. Bel progettino , la risposta poi del servo al movimento del nunchuck è immediata , direi in tempo reale , quindi servirà un ottimo servo con caratteristiche appropriate.
    Ero alla ricerca di un progettino per muovere una camera video a distanza di filo , ma solo muoverla orrizontalmente dapprima lo schema col potenziometro e dopo meglio quelli con i tastini era la soluzione ma pensandoci bene questa è una ottima soluzione avendo lo joy del nunchuck , proverò a realizzarlo per un PAN di videocamera , ma dovro apportare alcune modifiche , intanto l’erscursione orrizontale deve essere sui 90 gradi circa e possibilmente avere un effetto più rallentato del movilmento cioè se muovo a dx lo joystick il servo deve muoversi lentamente per permettere alla camera video di registrare bene poi avere pure un tastierino per cosi dire resettare il servo e riposizionare la camera video nella posizione iniziale di partenza .

    1. Ciao Maurizio,
      Rispetto ai gradi di escursione trovi delle variabili che puoi impostare come preferisci, io le ho impostate a 20 e 160 gradi.
      Il discorso velocità di risposta tra joystick e servo puoi controllare se la classe Servo.h abbia un parametro da impostare per rallentare il movimento, altrimenti puoi sostituire il metodo .write() con una funzione che sposti il servo di un grado ogni 200-300-400-500 millisecondo secondo le tue esigenze.
      Nel Blog dovresti trovare qualcosa di già fatto.

      Mauro

    • Fabio on 13 ottobre 2012 at 21:40
    • Reply

    Buonasera Mauro,

    ti scrivo perché sto cercando di realizzare un dispositivo Pan Tilt con arduino seguendo il tuo tutorial, ma aimè non riesco a farlo funzionare. fino alla seconda parte del tutorial va tutto e nel monitor seriale ho tutti i dati degli assi, ma quando vado a montare i servo e lo sketch della terza parte non va più nulla, nemmeno nel monitor ho più i dati degli accelerometri.

    tu mi sapresti aiutare?

    ti ringrazio.

    ciao

    Fabio

    1. Ciao Fabio,
      controlla i collegamenti verso i servomotori, sembra un problema di connessioni errate che manda in corto Arduino.
      E’ capitato anche a me in un’occasione ed il sintomo è proprio la disconnessione della porta seriale dal computer che non ti permette di vedere più i dati sul monitor seriale.

      Che tipo di servo stai utilizzando?

      Mauro

    • Roberto on 11 gennaio 2013 at 15:04
    • Reply

    ciao Mauro,

    non riesco ad utilizzare il tuo sketch! mi da questo errore: class twowire has no member named write

    dove sbaglio?

    1. Ciao Roberto,
      l’errore dice che non trova la classe, può succedere per 2 motivi:

      1. non hai scaricato la classe o l’hai installata male
      2. la versione dell’IDE non supporta quella classe

      Per il punto 1 verifica di averla scaricata e installata correttamente, per il punto 2 verifica che la classe sia stata scritta per la versione dell’IDE che stai utilizzando.

      Mauro

    • Francesco on 10 febbraio 2013 at 20:52
    • Reply

    Ciao,
    Perdona la mia ignoranza in materia, sto seguendo passo passo i progetti con il nunchuck ma non ho ben capito
    Come gestire le comunicazioni ( i fili) tra arduino , nunchuck e i due servo in quest’ ultimo.
    Potresti descrivermi in maniera approfondita i collegamenti?.
    Grazie ancora.

    1. Ciao Francesco,
      ti consiglio di acquistare un adattatore per nunchuck da pochi euro che ti semplifica la vita.
      Se non vuoi acquistare un adattatore già pronto puoi leggere uno dei miei articoli in cui descrivo passo-passo i collegamenti ed il modo di funzionamento del nunchuck con Arduino.

      Per i servo sono collegati ai pin 5 e 6, come leggi nello sketch.

      Mauro

    • Mattia on 6 maggio 2013 at 19:41
    • Reply

    Ciao,
    sono uno studente all’ultimo anno di itis, come tesina ho costruito un cannone in miniatura usa due servo motori e un nunchuck proprio come il progetto che hai costruito. il primo servo muove la casamatta dove e fissato il cannone mentre il secondo alza ed abbassa la canna. Ora ho letto i tuoi tutorial e visto che il funzionamento è molto simile ho provato ad usare il tuo sketch per muovere il mio progetto. Per il momento ho solo cambiato l’angolo di lavoro dei servo, ma dovrò ancora cambiare altro ed aggiungere qualche riga di codice. I servo raggiungono la posizione centrale, ma quando muovo la levetta niente, nessun movimento. Un’altra cosa: non ho acquistato l’adattatore ma ho comunque collegato i cavi. (rosso Vcc bianco GND giallo e verde ai pin analogici 4 e 5 di arduino, mi resta un cavetto nero che non so se debba essere collegato).
    Ho anche provato altri sketch simili ma proprio non ne vuole sapere, con i pulsanti e i resistori a sempre funzionato tutto e il nunchuck lo comprato solo oggi quindi non credo possa essere la fonte dei miei problemi.
    Quindi dopo averti assillato con i miei problemi ti ringrazio moltissimo per i tuoi tutorial e per il tuo sito che mi hanno insegnato molte più cose del mio professore e ti chiedo se sai dove potrebbe essere il mio problema
    Grazie ancora e ciao.

    Mattia

    1. Ciao Mattia,
      il tuo problema potrebbe essere il nunchuck.
      Se é originale ti consiglio di utilizzare l’adattatore che hai acquistato, se non lo é ci sono molti modelli in circolazione e non tutti funzionano allo stesso modo.
      Io ne ho provati 2/3 tipi ed alla fine l’unico veramente funzionante é l’originale.

      Prova il nunchuck senza i servo, fai degli sketch in cui i valori del joystick ti vengono scritti nel monitor seriale, potrebbero essere semplicemente differenti dai miei e quindi ti basta modificare i range di movimento.

      Mauro

    • Mattia on 14 maggio 2013 at 16:01
    • Reply

    Ciao,
    Ho finalmente risolto: ho comprato il nunchuck originale ho fatto le sketch per trovare i valori estremi ed ora finalmente il mio cannone si muove. Ancograzie per il sito e per il tuo prezioso aiuto
    Mattia

    1. Ciao Mattia,
      Ora che sei divenuto esperto del sistema, sketch e collegamenti puoi provare a capire come mai l’altro non ti funziona.

      Mauro

    • bruno on 7 gennaio 2014 at 13:14
    • Reply

    Ciao Mauro, che tipo di problemi avevi con i nunchuck non originali?

    Ne sto provando uno non originale e la sequenza di inizializzazione è diversa. Ho provato vari sketch prima di arrivare ad avere letture stabili. la cosa strana è che il joystick ha una risposta strana.
    Il mio ha come valore minimo 46, massimo 255 e a riposo 170.

    Con un programma solo per monitorare i valori e tradurli in quelli necessari per comandare dei motori tutto ok, sul 4WD se è sollevato va bene ma a terra a volte durante il movimento in avanti, quindi con lettura tra 170 e 255, i valori diventano per un attimo inferiori a 170. Sballa anche il fondo corsa a destra che invece di essere 255 diventa 46.

    Possibile che l’assorbimento dei motori con il carico + lentezza di codice e arduino + scarsa qualità del nunchuck mi sballi così tanto il risultato?

    1. Ciao Bruno,
      il primo problema che ho riscontrato riguardava proprio l’impossibilità di leggere valori stabili, risolto immediatamente con un prodotto originale.

      Il cambio di valori letti tra il 4WD libero nei movimenti e quando lo posizioni al suolo potrebbe dipendere dall’assorbimento dei motori, prova a verificare quanta corrente richiedono in fase di avanzamento e confronta i dati con i valori del nunchuck.

      Mauro

        • bruno on 9 gennaio 2014 at 10:29
        • Reply

        Ho risolto alimentando il nunchuck con i 5v del pacco batterie supplementare e con una sistemata al codice.

        1. Ottimo Bruno,
          ben fatto!!!

          Mauro

    • Giuseppe on 21 maggio 2014 at 10:56
    • Reply

    Ciao Mauro, sto cercando di costruire una testa mobile e vorrei comandarla attraverso il Nunchuck. Ho iniziato ora ad avvicinarmi al elettronica e non sono molto bravo con la programmazione, MI SERVE IL TUO AIUTO!! Oltre a muoverlo con il joystick vorrei poterlo bloccare in qualsiasi posizione semplicemente premendo Z sul Nunckuck e riportarlo nella posizione originale premendo nuovamente Z. Mi Aiuti? GRAZIE!

    1. Ciao Giuseppe,
      il mio aiuto è a disposizione di tutti gli appassionati arduino e makers, si chiamano articoli con sketch commentati e corsi.
      Puoi leggere tutti gli articoli in cui parlo di servo, nunchuck, pulsanti ecc.. e dalla comprensione delle mie spiegazioni trai le informazioni che ti servono.

    • FEDERICO on 17 ottobre 2014 at 19:24
    • Reply

    Ciao Mauro,
    si potrebbe usare lo sketch da te dato senza usare il monitor seriale o bisogna modificarlo?
    Scusa per la domanda che forse potrebbe essere banale, ma sono alle prime armi con arduino!!
    Grazie già da ora e congratulazioni per il tuo sito sempre molto dettagliato in tutto e per tutto!!!

    1. Ciao Federico,
      certo puoi usare lo sketch anche senza monitor seriale aperto.
      Se vuoi puoi commentare tutta la parte relativa ai Serial.xxxxxxxx per evitare di impegnare la memoria arduino.

      Mauro

    • Maurizio on 19 ottobre 2014 at 13:59
    • Reply

    Salve,
    le volevo chiedere,premettendo che sono alle prime armi con arduino e l’elettronica,come si facesse ad utilizzare anche i bottoni C e Z per comandare un servo con lo stesso sketch che c’e nella terza parte dell’articolo su “arduino e nunchuck”.
    La ringrazio già da ora per una sua eventuale risposta e mi congratulo con lei per il suo sito web, molto utile per tutti gli appassionati alle prime armi!!!!

    1. Ciao Maurizio,
      nella descrizione dello sketch trovi il commento linea per linea e puoi notare come controllo ed uso i pulsanti C e Z.
      Se desideri comprendere meglio il funzionamento del nunchuck puoi leggere anche gli altri articoli che ho dedicato a questo prodotto.

Lascia un commento

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.