Cosa puoi fare con un arduino, un nunchuck, due servomotori, del cartone e del nasto adesivo?
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:
quindi passa a montare l’altra squadretta su uno dei server, anche in questo caso con del nastro adesivo:
quindi monta tutto in modo che i due servo si trovino a 90° l’uno rispetto all’altro:
ed infine monta la testa di cartone sul serve in alto:
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:
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
24 pings
Skip to comment form