Posted in Arduino | 0 comments

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

  1. We will need a fresh blank sketch. Go into the File menu and choose New.
  2. 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);
      }
    }
  3. Save the code on your computer with a filename that makes sense.
  4. 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:
    • Yellow from GEMMA DO to NeoPixels IN
    • Red from GEMMA Vout to NeoPixels PWR
    • Black from GEMMA GND to NeoPixels GND
    • White from GEMMA D2 to button
    • Green from GEMMA GND to other side of the buttonneopixel wiring 2
  5. Plug the GEMMA into your computer’s USB port, if it’s not already.
  6. Upload the code. Remember to press the button on the GEMMA before uploading.
  7. After uploading, the GEMMA should be running the code. A soft rainbow pattern will circle.
  8. 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.
  9. 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.

  1. 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                         //
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
  2. 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.
  3. 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                         //
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
  4. 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?
  5. 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)
  6. 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.
  7. Be sure to save your file as you iterate.
  8. Now we are ready to move onto the final section.

part4-leftpart6-right

 

Cover photo by me. 😉