Rhythm Hand
This cyberglove is about making the right move at the right moment.
The lights are going from your arm (elbow) to your hand and when the lights arrive at your hand your have to press your fingers on the mini photocell.
If you press your hand on the mini photocell at the right moment the leds turn green. If not, the leds turn red.
Collect Materials
- A glove
- Fabric to make the glove longer
- WS2812B LED strip
- Wires
- Arduino
- Mini photosell
Making Circuits
First connect the led strip to the arduino. You can do that by connecting the +5v to the 5v on the arduino. The Din has to be connected to A0 on the arduino and the GND has to be connected to the GND on the arduino.
You also have to connect the mini photocell to the arduino through connecting to the 5v wire from the led strip and from the same source connecting with a wire to PIN 6 on the arduino. The other side from the mini photocell has to be connected to the GND wire from the led strip
Designing the Glove
The glove has to have the right size to fit the led strips. The leds have to be aligned to make more enjoyable to look at.
For this game you have to use your arm and you want to be able to move freely. This can be realised by putting the arduino on the glove. I used velcro as a fastener to stick the arduino to the glove. Then for establishing more stability you can put a rope around the glove and around the arduino.
The mini photocell has been sewed inside the glove so it will stay in place.
Lastly you have to hide the wires to make it look better. That can be done with fabric that will be sewed on top of the wires.
Soldering
Now you can make the connecting wires from the circuit secure by soldering.
Coding
// A basic everyday NeoPixel strip test program.
// NEOPIXEL BEST PRACTICES for most reliable operation: // - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections. // - MINIMIZE WIRING LENGTH between microcontroller board and first pixel. // - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR. // - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS // connect GROUND (-) first, then +, then data. // - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip, // a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED. // (Skipping these may work OK on your workbench but can fail in the field)
#include #ifdef __AVR__ #include // Required for 16 MHz Adafruit Trinket #endif
// Which pin on the Arduino is connected to the NeoPixels? // On a Trinket or Gemma we suggest changing this to 1: #define LED_PIN 6
// How many NeoPixels are attached to the Arduino? #define LED_COUNT 60
// Declare our NeoPixel strip object: Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); uint32_t color = strip.Color(127,127,127); // White color, for default bool clickedCorrectly = false; // Argument 1 = Number of pixels in NeoPixel strip // Argument 2 = Arduino pin number (most are valid) // Argument 3 = Pixel type flags, add together as needed: // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
// setup() function -- runs once at startup --------------------------------
void setup() { // These lines are specifically to support the Adafruit Trinket 5V 16 MHz. // Any other board, you can remove this part (but no harm leaving it): #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif // END of Trinket-specific code.
pinMode(A0, INPUT); strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) strip.show(); // Turn OFF all pixels ASAP strip.setBrightness(10); // Set BRIGHTNESS to about 1/5 (max = 255) }
// loop() function -- runs repeatedly as long as board is on ---------------
void loop() { clickedCorrectly = theaterChaseOne(color); if (clickedCorrectly) { color = strip.Color(0,255,0); } else { color = strip.Color(255, 0, 0); } }
// Some functions of our own for creating animated effects -----------------
// Theater-marquee-style chasing lights. Pass in a color (32-bit value, // a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms) // between frames. bool theaterChaseOne(uint32_t color) { bool correct = false; bool clickedWrong = false; for (int index = 0; index < 18; index++) { //loop int value = analogRead(A0); if (value > 800) { //value light sensor if (index < 16) { //2 leds before end then you can click color = strip.Color(255,0,0); //red color leds clickedWrong = true; //clicked wrong then leds turn red } else if (!clickedWrong) { //if not wrong color = strip.Color(0,255,0); //green color leds correct = true; //clicked correct then leds turn green } } strip.clear(); strip.setPixelColor(17 - index, color); //first row led lights strip.setPixelColor(18 + index, color); //second row led lights strip.setPixelColor(53 - index, color); //third row led lights strip.show(); delay(300); } return correct; }
Changes
I made some changes. Firstly I hid the arduino so it would be more comfortable to use the "Rythm hand" and secondly I changed the code a little bit. I changed the code so that when you press at the right moment the color becomes green and the LEDS move faster. By doing so the LED Swill become 10% faster then before. This makes the game more interesting
This is how the code is now:
// A basic everyday NeoPixel strip test program. // NEOPIXEL BEST PRACTICES for most reliable operation: // - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections. // - MINIMIZE WIRING LENGTH between microcontroller board and first pixel. // - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR. // - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS // connect GROUND (-) first, then +, then data. // - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip, // a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED. // (Skipping these may work OK on your workbench but can fail in the field) #include #ifdef __AVR__ #include // Required for 16 MHz Adafruit Trinket #endif // Which pin on the Arduino is connected to the NeoPixels? // On a Trinket or Gemma we suggest changing this to 1: #define LED_PIN 6 // How many NeoPixels are attached to the Arduino? #define LED_COUNT 60 // Declare our NeoPixel strip object: Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); uint32_t color = strip.Color(127,127,127); // White color, for default bool clickedCorrectly = false; int index = 0; int interval = 300; int result = 0; unsigned long previousMs = millis(); // Argument 1 = Number of pixels in NeoPixel strip // Argument 2 = Arduino pin number (most are valid) // Argument 3 = Pixel type flags, add together as needed: // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) // NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) // NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products) // setup() function -- runs once at startup -------------------------------- void setup() { // These lines are specifically to support the Adafruit Trinket 5V 16 MHz. // Any other board, you can remove this part (but no harm leaving it): #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif // END of Trinket-specific code. Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } pinMode(A0, INPUT); strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) strip.show(); // Turn OFF all pixels ASAP strip.setBrightness(10); // Set BRIGHTNESS to about 1/5 (max = 255) } // loop() function -- runs repeatedly as long as board is on --------------- void loop() { unsigned long currentMs = millis(); // Getting the current time int value = analogRead(A0); // Reading the current light sensor if (value > 900 && result == 0) { //If the sensor is pressed and no result has been recorded yet, trigger result capture if (index < 16) { //2 leds before end then you can click color = strip.Color(255,0,0); //red color leds result = 1; //clicked wrong then leds turn red } else { //if correct color = strip.Color(0,255,0); //green color leds result = 2; //clicked correct then leds turn green } } if (currentMs - previousMs >= interval) { // Check if the current loop exceeds the interval previousMs = currentMs; // Set the new interval to the current time + interval index += 1; // Set the leds one step further in the loop if (index > 17) { // Trigger end of loop handling index = 0; if (result == 2) { // On a correct result interval = (int)max((interval * 0.95), 50); // Speed up by 10%, down to 50ms interval/ color = strip.Color(0,255,0); // Set the leds to green } else if (result == 1) { // On an incorrect result interval = 300; // Reset the interval color = strip.Color(255, 0, 0); // Set the leds to red } else { // On no result captured color = strip.Color(255, 0, 0); // Set the leds to red } result = 0; // Reset the result for the next loop } theaterChaseOne(color, index); // Light up the leds for display. } } // Some functions of our own for creating animated effects ----------------- // Theater-marquee-style chasing lights. Pass in a color (32-bit value, // a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms) // between frames. void theaterChaseOne(uint32_t color, int index) { strip.clear(); strip.setPixelColor(17 - index, color); //first row led lights strip.setPixelColor(18 + index, color); //second row led lights strip.setPixelColor(53 - index, color); //third row led lights strip.show(); }