Arduino animatörerna-gör din awesome kostymer mer awesome! (10 / 15 steg)
Steg 10: Nunchuck kontroll
Jag skrev denna bit kod tillbaka under 2007 att använda en Wii nunchuck som en inmatningsenhet för en animatronic Predator kanon (se exempel 7). Wii nunchuck kommunicerar till en Arduino över fyra ledningar (power, marken, data och klocka) med ett I²C gränssnitt (mellan integrerad krets aka tvåträdsförbindelser gränssnitt eller TWI.)
Wii nunchuck har en tre-axlig accelerometer, joystick och två tryckknappar-för $20 är det en awesome inmatningsenhet för Arduino projekt. Koden som presenteras här är en ytterligare ändring av koden Tod Kurt som presenterades i hans Bionic Arduino klass-jag helt enkelt utökade det för att styra allt utom den accelerometer Z axeln, som jag hittade jag sällan används.
Med denna kod kan du styra fyra servon accelerometer och joystick funktion och använda de två tryckknapparna för att vända på lysdioder (eller transistorer eller jämn springa en bit kod.)
/*
* Exempel 6
* Nunchuck kontroll för fyra servon och två knappen ingångar
* Honus 2007
* Detta tillåter användning av en Wii nunchuck som en inmatningsenhet och är ändrade och utökade från den ursprungliga koden
* av Tod E. Kurt och Windmeadow Labs
* 2007 Tod E. Kurt, http://todbot.com/blog/
* Wii Nunchuck läsa koden tas från Windmeadow Labs, http://www.windmeadow.com/node/42
*/
#include "Wire.h"
int ledPin1 = 13. Kontroll stift för LED 1
int ledPin2 = 12; Kontroll stift för LED 2
int servoPin1 = 9; Kontroll stift för servomotor
int servoPin2 = 8; Kontroll stift för servomotor
int servoPin3 = 7. Kontroll stift för servomotor
int servoPin4 = 6; Kontroll stift för servomotor
int pulseWidth1 = 0; Belopp till puls servo 1
int pulseWidth2 = 0; Belopp till puls servo 2
int pulseWidth3 = 0; Belopp till puls servo 3
int pulseWidth4 = 0; Belopp till puls servo 4
int refreshTime = 20; tiden i millisecs behövs mellan pulser
lång lastPulse1;
lång lastPulse2;
lång lastPulse3;
lång lastPulse4;
int minPulse = 700; minsta pulse bredd
int loop_cnt = 0;
void setup()
{
Serial.BEGIN(19200);
pinMode (servoPin1, produktionen); Ställ in servo pin som en utgångsstiftet
pinMode (servoPin2, produktionen); Ställ in servo pin som en utgångsstiftet
pinMode (servoPin3, produktionen); Ställ in servo pin som en utgångsstiftet
pinMode (servoPin4, produktionen); Ställ in servo pin som en utgångsstiftet
pulseWidth1 = minPulse; Ange motor position till ett minimum
pulseWidth2 = minPulse; Ange motor position till ett minimum
pulseWidth3 = minPulse; Ange motor position till ett minimum
pulseWidth4 = minPulse; Ange motor position till ett minimum
nunchuck_init(); Skicka initilization handslag
Serial.Print ("NunchuckServo ready\n");
}
void loop()
{
checkNunchuck1();
updateServo1(); uppdatera servo 1 position
checkNunchuck2();
updateServo2(); uppdatera servo 2 position
checkNunchuck3();
updateServo3(); uppdatera servo 3 position
checkNunchuck4();
updateServo4(); uppdatera servo 4 position
om (nunchuck_zbutton()) / / ljus LED om z-knappen trycks
digitalWrite (ledPin1, hög);
annat
digitalWrite(ledPin1,LOW);
om (nunchuck_cbutton()) / / ljus LED om c knapp trycks
digitalWrite (ledPin2, hög);
annat
digitalWrite(ledPin2,LOW);
Delay(1); Detta är här att ge en känd tid per slinga
}
void checkNunchuck1()
{
om (loop_cnt > 100) {/ / loop () s är varje 1msec, detta är varje 100msec
nunchuck_get_data();
nunchuck_print_data();
flyta tilt = nunchuck_accelx(); x-axeln, i detta fall sträcker sig från ~ 70 - ~ 185
lutning = (tilt - 70) * 1,5; konvertera till vinkeln i grader, ungefär
pulseWidth1 = (luta * 9) + minPulse; konvertera vinkel till mikrosekunder
loop_cnt = 0; återställa för
}
loop_cnt ++;
}
kallas varje loop().
använder globala variabler servoPin, pulsewidth, lastPulse och refreshTime
void updateServo1()
{
puls servo igen om rhe uppdateringstid (20 ms) har gått:
om (millis() - lastPulse1 > = refreshTime) {
digitalWrite (servoPin1, hög); Aktivera motorn
delayMicroseconds(pulseWidth1); Längden på pulsen anger motor
digitalWrite (servoPin1, låg); Stänga av motorn
lastPulse1 = millis(); Spara tiden för den sista pulsen
}
}
void checkNunchuck2()
{
om (loop_cnt > 100) {/ / loop () s är varje 1msec, detta är varje 100msec
nunchuck_get_data();
nunchuck_print_data();
flyta tilt = nunchuck_accely(); y-axeln, i detta fall sträcker sig från ~ 70 - ~ 185
lutning = (tilt - 70) * 1,5; konvertera till vinkeln i grader, ungefär
pulseWidth2 = (luta * 9) + minPulse; konvertera vinkel till mikrosekunder
loop_cnt = 0; återställa för
}
loop_cnt ++;
}
kallas varje loop().
använder globala variabler servoPin, pulsewidth, lastPulse och refreshTime
void updateServo2()
{
puls servo igen om rhe uppdateringstid (20 ms) har gått:
om (millis() - lastPulse2 > = refreshTime) {
digitalWrite (servoPin2, hög); Aktivera motorn
delayMicroseconds(pulseWidth2); Längden på pulsen anger motor
digitalWrite (servoPin2, låg); Stänga av motorn
lastPulse2 = millis(); Spara tiden för den sista pulsen
}
}
void checkNunchuck3()
{
om (loop_cnt > 100) {/ / loop () s är varje 1msec, detta är varje 100msec
nunchuck_get_data();
nunchuck_print_data();
flyta tilt = nunchuck_joyx(); x-axeln, i detta fall sträcker sig från ~ 70 - ~ 185
lutning = (tilt - 70) * 1,5; konvertera till vinkeln i grader, ungefär
pulseWidth3 = (luta * 9) + minPulse; konvertera vinkel till mikrosekunder
loop_cnt = 0; återställa för
}
loop_cnt ++;
}
kallas varje loop().
använder globala variabler servoPin, pulsewidth, lastPulse och refreshTime
void updateServo3()
{
puls servo igen om rhe uppdateringstid (20 ms) har gått:
om (millis() - lastPulse3 > = refreshTime) {
digitalWrite (servoPin3, hög); Aktivera motorn
delayMicroseconds(pulseWidth3); Längden på pulsen anger motor
digitalWrite (servoPin3, låg); Stänga av motorn
lastPulse3 = millis(); Spara tiden för den sista pulsen
}
}
void checkNunchuck4()
{
om (loop_cnt > 100) {/ / loop () s är varje 1msec, detta är varje 100msec
nunchuck_get_data();
nunchuck_print_data();
flyta tilt = nunchuck_joyy(); y-axeln, i detta fall sträcker sig från ~ 70 - ~ 185
lutning = (tilt - 70) * 1,5; konvertera till vinkeln i grader, ungefär
pulseWidth4 = (luta * 9) + minPulse; konvertera vinkel till mikrosekunder
loop_cnt = 0; återställa för
}
loop_cnt ++;
}
kallas varje loop().
använder globala variabler servoPin, pulsewidth, lastPulse och refreshTime
void updateServo4()
{
puls servo igen om rhe uppdateringstid (20 ms) har gått:
om (millis() - lastPulse4 > = refreshTime) {
digitalWrite (servoPin4, hög); Aktivera motorn
delayMicroseconds(pulseWidth4); Längden på pulsen anger motor
digitalWrite (servoPin4, låg); Stänga av motorn
lastPulse4 = millis(); Spara tiden för den sista pulsen
}
}
//
Nunchuck funktioner
//
statisk uint8_t nunchuck_buf [6]. matrisen att lagra nunchuck data,
initiera I2C systemet, gå med I2C bussen,
och berätta nunchuck vi pratar till den
void nunchuck_init()
{
Wire.BEGIN(); gå med i2c bussen som master
Wire.beginTransmission(0x52); överföra till enhet 0x52
Wire.send(0x40); skickar minnesadress
Wire.send(0x00); skickar skickade en nolla.
Wire.endTransmission(); stoppa överföring
}
Skicka en begäran om data till nunchuck
var "send_zero()"
void nunchuck_send_request()
{
Wire.beginTransmission(0x52); överföra till enhet 0x52
Wire.send(0x00); skickar en byte
Wire.endTransmission(); stoppa överföring
}
Få data tillbaka från nunchuck,
Returnerar 1 om framgångsrika read. returnerar 0 om fel
int nunchuck_get_data()
{
int cnt = 0;
Wire.requestFrom (0x52, 6); begäran data från nunchuck
medan (Wire.available ()) {
ta emot byte som ett heltal
nunchuck_buf [cnt] = nunchuk_decode_byte(Wire.receive());
CNT ++;
}
nunchuck_send_request(); skicka begäran om nästa datanyttolasten
Om vi fått 6 byte, gå sedan skriva ut dem
om (cnt > = 5) {
tillbaka 1. framgång
}
Return 0; misslyckande
}
Skriva ut indata har vi fått
accel data är 10 bitar lång
så vi läsa 8 bitar, då måste vi lägga till
på de sista 2 bitarna. Det är därför jag
multiplicera dem med 2 * 2
void nunchuck_print_data()
{
statisk int jag = 0;
int joy_x_axis = nunchuck_buf [0];
int joy_y_axis = nunchuck_buf [1].
int accel_x_axis = nunchuck_buf [2]. // * 2 * 2;
int accel_y_axis = nunchuck_buf [3]. // * 2 * 2;
int accel_z_axis = nunchuck_buf [4]. // * 2 * 2;
int z_button = 0;
int c_button = 0;
byte nunchuck_buf [5] innehåller bitar för z- och c-knapparna
den innehåller också de minst signifikanta bitarna för accelerometer data
så vi måste kontrollera varje bit av byte outbuf [5]
om ((nunchuck_buf [5] >> 0) & 1)
z_button = 1;
om ((nunchuck_buf [5] >> 1) & 1)
c_button = 1;
om ((nunchuck_buf [5] >> 2) & 1)
accel_x_axis += 2.
om ((nunchuck_buf [5] >> 3) & 1)
accel_x_axis + = 1;
om ((nunchuck_buf [5] >> 4) & 1)
accel_y_axis += 2.
om ((nunchuck_buf [5] >> 5) & 1)
accel_y_axis + = 1;
om ((nunchuck_buf [5] >> 6) & 1)
accel_z_axis += 2.
om ((nunchuck_buf [5] >> 7) & 1)
accel_z_axis + = 1;
Serial.Print(i,dec);
Serial.Print("\t");
Serial.Print("Joy:");
Serial.Print(joy_x_axis,dec);
Serial.Print(",");
Serial.Print (joy_y_axis, DEC);
Serial.Print ("\t");
Serial.Print("ACC:");
Serial.Print (accel_x_axis, DEC);
Serial.Print(",");
Serial.Print (accel_y_axis, DEC);
Serial.Print(",");
Serial.Print (accel_z_axis, DEC);
Serial.Print("\t");
Serial.Print("but:");
Serial.Print (z_button, DEC);
Serial.Print(",");
Serial.Print (c_button, DEC);
Serial.Print("\r\n"); newline
i ++;
}
Koda data om du vill formatera som de flesta wiimote förare utom
behövs endast om du använder en av de regelbundna wiimote förarna
char nunchuk_decode_byte (char x)
{
x = (x ^ 0x17) + 0x17;
återvändande x;
}
Returnerar zbutton stat: 1 = pressad, 0 = notpressed
int nunchuck_zbutton()
{
tillbaka ((nunchuck_buf [5] >> 0) & 1)? 0: 1; Voodoo
}
Returnerar zbutton stat: 1 = pressad, 0 = notpressed
int nunchuck_cbutton()
{
tillbaka ((nunchuck_buf [5] >> 1) & 1)? 0: 1; Voodoo
}
Returnerar värdet på x-axeln joystick
int nunchuck_joyx()
{
återgå nunchuck_buf [0];
}
Returnerar värdet på y-axeln joystick
int nunchuck_joyy()
{
återgå nunchuck_buf [1].
}
Returnerar värdet för x-axeln accelerometer
int nunchuck_accelx()
{
återgå nunchuck_buf [2]. FIXME: detta lämnar ut 2-bitar av data
}
Returnerar värdet för y-axeln accelerometer
int nunchuck_accely()
{
återgå nunchuck_buf [3]. FIXME: detta lämnar ut 2-bitar av data
}
Returnerar värdet på z-axeln accelerometer
int nunchuck_accelz()
{
återgå nunchuck_buf [4]. FIXME: detta lämnar ut 2-bitar av data
}