MCN Workshop Part 5
On the previous parts, we wired a simple input button and next wired NeoPixels for flashy output. Now we’ll combine both input and output.
Interactions
- We will need a fresh blank sketch. Go into the
File
menu and chooseNew
. - Copy and paste the following 257 lines of code.
/* Created by chris@drumminhands.com Modified by combining these tutorials Blink without Delay http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay State change detection (edge detection) http://arduino.cc/en/Tutorial/ButtonStateChange Adafruit Strandtest https://github.com/adafruit/Adafruit_NeoPixel Debounce http://www.arduino.cc/en/Tutorial/Debounce Cyclon eyes https://github.com/EternalCore/NeoPixel_Cylon_Scrolling_Eye */ //Choose a default program to run all the time, until the button is pressed. //Then run the second program for a time. Then go back to the original program. #include <Adafruit_NeoPixel.h> // constants won't change. #define neoPixelPin 0 // the number of the neopixel pic #define buttonPin 2 // the number of the input pin #define numPixelsInStrip 12 // the number of pixels in the strip/circle Adafruit_NeoPixel strip = Adafruit_NeoPixel(numPixelsInStrip, neoPixelPin, NEO_GRB + NEO_KHZ800); ////////////////////////////////////////////////////////////////////////////////////// // Change the following variables to play with different outcomes // // int defaultBrightness = 128; // the max brightness, between 0 and 256 // int reactionDuration = 2000; // how long to run the second program, in miliseconds // // // Do not change anything outside of this comment box, unless you know what it does.// ////////////////////////////////////////////////////////////////////////////////////// // Variables used in programs int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin long lastDebounceTime = 0; // the last time the output pin was toggled long debounceDelay = 50; // the debounce time; increase if the output flickers int programState = 0; // current program seleted int ledState = HIGH; // the current state of the output pin long previousMillis = 0; // will store last time LED was updated int neoPixelToChange = 0; //track which neoPixel to change int neoPixel_j = 0; //stores values for program cycles long color = 0x01000000; //store the color value when reacting // Setup is a program run once at the beginning to get things in place void setup() { pinMode(buttonPin, INPUT_PULLUP); strip.begin(); // prep the NeoPixels strip.show(); // Initialize all pixels to 'off' strip.setBrightness(defaultBrightness); // initialize brightness } // Loop is the program that runs repeatedly after Setup. Look for the programs below to change. void loop() { // read the state of the switch into a local variable: int reading = digitalRead(buttonPin); // check to see if you just pressed the button // If the switch changed, due to noise or pressing: if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { //change the program programState = 1; //change to the second program color = random(0x01000000); // choose a color at random for the reaction } } } // save the reading. Next time through the loop lastButtonState = reading; // if it's been longer than the reaction duration if ((millis() - lastDebounceTime) > reactionDuration) { programState = 0; //go back to the default program } //run the chosen program switch (programState) { case 0: /////////////////////////////////////////////////////////////////////////////////////////// rainbowCycle(7); //The default program. Change as needed // /////////////////////////////////////////////////////////////////////////////////////////// break; case 1: ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// blinkColor(color,100); // use this line to blink a random color // //blinkColor((unsigned long)random(0x01000000),100); // use this line to blink a new random color each blink // //blinkColor(strip.Color(128,0,204),100); // use this line to blink a specific color // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// break; default: allColor(strip.Color(0,0,0)); //if nothing else matches, turn all off } } // Fill all the dots with one color void allColor(uint32_t c) { for(uint16_t i=0; i<strip.numPixels(); i++) { strip.setPixelColor(i, c); strip.show(); } } // note for a random color, use: // allColor((unsigned long)random(0x01000000)); // random color void blinkColor(uint32_t c, uint8_t wait) { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > wait) { // save the last time you blinked the LED previousMillis = currentMillis; // if the LED is off turn it on and vice-versa: if (ledState == LOW){ ledState = HIGH; allColor(c); } else { ledState = LOW; allColor(strip.Color(0,0,0)); // off } } } // Fill the dots one after the other with a color void colorWipe(uint32_t c, uint8_t wait) { unsigned long currentMillis = millis(); //only do this if some of the pixels still need to be lit if (neoPixelToChange <= strip.numPixels()){ if(currentMillis - previousMillis > wait) { // save the last time you changed a NeoPixel previousMillis = currentMillis; //change a pixel strip.setPixelColor(neoPixelToChange, c); strip.show(); neoPixelToChange++; } } } // Fill the dots one after the other with a color void colorWipeCycle(uint32_t c, uint8_t wait) { unsigned long currentMillis = millis(); //only do this if some of the pixels still need to be lit if (neoPixelToChange <= strip.numPixels()){ if(currentMillis - previousMillis > wait) { // save the last time you changed a NeoPixel previousMillis = currentMillis; //change a pixel strip.setPixelColor(neoPixelToChange, c); strip.show(); neoPixelToChange++; } } else { // reset the cycle previousMillis = 0; neoPixelToChange = 0; allColor(strip.Color(0,0,0)); } } void rainbow(uint8_t wait) { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > wait) { // save the last time you changed a NeoPixel previousMillis = currentMillis; //change the colors of the pixels uint16_t i; for(i=0; i<strip.numPixels(); i++) { strip.setPixelColor(i, Wheel((i+neoPixel_j) & 255)); } strip.show(); neoPixel_j = (neoPixel_j + 1) % 255; //increment j until all colors are used, then start over } } // Slightly different, this makes the rainbow equally distributed throughout void rainbowCycle(uint8_t wait) { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > wait) { // save the last time you changed a NeoPixel previousMillis = currentMillis; //change the colors of the pixels uint16_t i; for(i=0; i<strip.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + neoPixel_j) & 255)); } strip.show(); neoPixel_j = (neoPixel_j + 1) % 1279; // 5 cycles of all colors on wheel, then start over } } void softBlink(uint32_t c, uint8_t brightness, uint8_t wait) { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > wait) { //set the color of all pixels allColor(c); // is there a way to set this only once per program ???????????????????? // save the last time you changed a NeoPixel previousMillis = currentMillis; uint16_t i; int b = (neoPixel_j * brightness) / brightness; strip.setBrightness(b); strip.show(); // sometime figure out how to get this to fade down too instead of just restarting ////////////////////// neoPixel_j = (neoPixel_j + 1) % brightness; } } // Input a value 0 to 255 to get a color value. // The colours are a transition r - g - b - back to r. uint32_t Wheel(byte WheelPos) { if(WheelPos < 85) { return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } else if(WheelPos < 170) { WheelPos -= 85; return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } else { WheelPos -= 170; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } }
- Save the code on your computer with a filename that makes sense.
- The circuit should already be setup, as long as you did not unplug the button when you plugged in the NeoPixels. If you need to tweak, be sure unplug the GEMMA from your computer before changing the circuit. Double-check the following:
- Plug the GEMMA into your computer’s USB port, if it’s not already.
- Upload the code. Remember to press the button on the GEMMA before uploading.
- After uploading, the GEMMA should be running the code. A soft rainbow pattern will circle.
- Try pushing the button. The NeoPixels should do something very different for a few seconds and then go back to the original soft rainbow pattern.
- What’s happening here is the output changes depending on the input. It reacts to you.
Tweak the code
Now let’s tweak the code, just a bit. Don’t be scared. Let’s make some changes to customize this for you.
- Scroll down in the code until you find a section that looks like this:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// blinkColor(color,100); // use this line to blink a random color // //blinkColor((unsigned long)random(0x01000000),100); // use this line to blink a new random color each blink // //blinkColor(strip.Color(128,0,204),100); // use this line to blink a specific color // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- Notice only one line has different color in the text. The others are “commented out,” meaning that there are two slashes (
//
) at the start of the line. This means that you can type anything you want after those slashes and those characters won’t influence the behavior at all. It’s a way for you to write comments for yourself or others who read the code. It is also a way to hide particular lines of code for later use. - Add two comment slashes to line 97 and un-comment line 99, similar to below:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //blinkColor(color,100); // use this line to blink a random color // //blinkColor((unsigned long)random(0x01000000),100); // use this line to blink a new random color each blink // blinkColor(strip.Color(128,0,204),100); // use this line to blink a specific color // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- With this change, the NeoPixels will do something different when the button is pushed. Save the file and upload it. Give the button a try. What color does it change to?
- Now tweak the code to your liking. Change the color value to anything you want. This is the specific part that sets the color, with three values, one each for Red, Green, and Blue.
strip.Color(128,0,204)
- Each of the three values can a whole number from 0 to 255. Change the values and try uploading it again. Maybe use a color picker to get the RGB values you want.
- Be sure to save your file as you iterate.
- Now we are ready to move onto the final section.