/* * Wii Nunchuk with Teensy I2C example * * We use the Nunchuk accellerometers and display the result in a graph (using the Monitor app) * The Monitor application was made by Kasper Kamperman, and can be found as part of the AS3Glue package: * http://as3glue.googlecode.com/files/arduino_as3glue_bundle_v16.zip * * In this sketch, we also show how a movement Left or Right can be detected by the nunchuk and translated into a keystroke on the computer. * * See http://www.pjrc.com/teensy/td_libs_Wire.html for the Wire (I2C) library: * The SCL line is on pin 0 of the Teensy 2.0++ (pin 5 on Teensy2.0) and is conected to the "c" (last) on the Wii adapter * The SDA line is on pin 1 of the Teensy 2.0++ (pin 6 on Teensy2.0) and is connected to the "d" (next to last) on the Wii adapter * Both SDA and SCL are also connected to the +5v via a couple of 1k8 resistors. (This really helps!) * The power and ground pins of the Wii Adapter are connected to +5V and ground respectively. * * Version 1, 25 March 2011 * Copyright 2011 Gidi van Liempd (gidi@geedesign.com) * This code can be freely distributed, but I do like some credit for my small contribution to science ;-) * */ #include #include "nunchuck_funcs.h" #include #define SCALE_X (4) #define SCALE_Y (4) #define SCALE_Z (4) #define SCALE_X2 (4) #define SCALE_Y2 (4) #define SCALE_Z2 (4) /* analog inputs */ int analogInputsToReport = 0; // bitwise array to store pin reporting int analogPin = 0; // counter for reading analog pins #define ANALOG_PINS (6) int display_values[ANALOG_PINS]; // array for displaying values #define ALPHA_X (0.01) #define THRESHOLD_L (250) #define THRESHOLD_R (250) #define REPEAT_DELAY (200) #define INTERVAL_DELAY (200) int prev_value_X = 0; float result_value_X; float prev_result_value_X = 0.0; #define ALPHA_Y (0.01) int prev_value_Y = 0; float result_value_Y; float prev_result_value_Y = 0.0; #define ALPHA_Z (0.01) int prev_value_Z = 0; float result_value_Z; float prev_result_value_Z = 0.0; boolean Rpressed = false; boolean Lpressed = false; unsigned long lasttimeL; // last time Lpressed went active unsigned long lasttimeR; // last time Rpressed went active unsigned long presenttime; // ----------------------------------------------------------------------------- // sets bits in a bit array (int) to toggle the reporting of the analogIns // ----------------------------------------------------------------------------- void reportAnalogCallback(byte pin, int value) { if(value == 0) { analogInputsToReport = analogInputsToReport &~ (1 << pin); } else { // everything but 0 enables reporting of that pin analogInputsToReport = analogInputsToReport | (1 << pin); } } // ----------------------------------------------------------------------------- // Setup // ----------------------------------------------------------------------------- void setup() { nunchuck_init(); // send the initilization handshake Firmata.setFirmwareVersion(0, 2); Firmata.attach(REPORT_ANALOG, reportAnalogCallback); // we will pass measurements to the computer Firmata.begin(); // intialize timers presenttime = millis(); lasttimeL = presenttime; lasttimeR = presenttime; } // ----------------------------------------------------------------------------- // Loop // ----------------------------------------------------------------------------- void loop() { // take a measurement nunchuck_get_data(); // display raw values display_values[0] = SCALE_X * nunchuck_accelx(); // raw value accellerometer X display_values[1] = SCALE_Y * nunchuck_accely(); // raw value accellerometer Y display_values[2] = SCALE_Z * nunchuck_accelz(); // raw value accellerometer Z // 1] Compute filtered values result_value_X = (ALPHA_X * nunchuck_accelx()) + ((1 - ALPHA_X) * prev_result_value_X); result_value_Y = (ALPHA_Y * nunchuck_accely()) + ((1 - ALPHA_Y) * prev_result_value_Y); result_value_Z = (ALPHA_Z * nunchuck_accelz()) + ((1 - ALPHA_Z) * prev_result_value_Z); // 2] What values to display? display_values[3] = SCALE_X2 * result_value_X; display_values[4] = SCALE_Y2 * result_value_Y; //display_values[5] = SCALE_Z2 * result_value_Z; presenttime = millis(); // check for L signal if ((display_values[0] - display_values[3]) > THRESHOLD_L) { // condition for Lpressed is true if (((presenttime - lasttimeL) > REPEAT_DELAY) && ((presenttime - lasttimeR) > INTERVAL_DELAY)) { // we can safely give the Lpressed signal Lpressed = true; // Uncomment the following line if you want a L keystroke to be passed on a left movement // (N.B. In that case you must compile the sketch with Tools > USB Type > Keyboard + Mouse) //Keyboard.print("L"); lasttimeL = presenttime; } } else { Lpressed = false; }; // check for R signal if ((display_values[3] - display_values[0]) > THRESHOLD_R) { // condition for Rpressed is true if (((presenttime - lasttimeR) > REPEAT_DELAY) && ((presenttime - lasttimeL) > INTERVAL_DELAY)) { // we can safely give the Rpressed signal Rpressed = true; // Uncomment the following line if you want a R keystroke to be passed on a right movement // (N.B. In that case you must compile the sketch with Tools > USB Type > Keyboard + Mouse) //Keyboard.print("R"); lasttimeR = presenttime; } } else { Rpressed = false; }; // display values if (Lpressed && Rpressed) { display_values[5] = 900; // values are abritrary, just to show a peak } else if (Rpressed) { display_values[5] = 600; // values are abritrary, just to show a peak } else if (Lpressed) { display_values[5] = 300; // values are abritrary, just to show a peak } else { display_values[5] = 0; }; // 3] record values for the next turn prev_value_X = nunchuck_accelx(); // the raw measured value prev_result_value_X = result_value_X; // the filtered value // prev_value_Y = nunchuck_accely(); // the raw measured value prev_result_value_Y = result_value_Y; // the filtered value // prev_value_Z = nunchuck_accelz(); // the raw measured value prev_result_value_Z = result_value_Z; // the filtered value while(Firmata.available()) Firmata.processInput(); for(analogPin=0;analogPin< ANALOG_PINS;analogPin++) { if( analogInputsToReport & (1 << analogPin) ) Firmata.sendAnalog(analogPin, display_values[analogPin] ); }; delay(10); }