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:    https://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.

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

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

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.