Neopixels and button control

There's a comment that explains that, do you need help understanding the comment?

so, its fine, i been staring at the code i posted in previous working out where to add it and how, but to no avail.

i gotta focus on one part at a time lol

so yeah i cant work out where to add this into the edited code in order to break up the delay in the fade sequence

#include <Adafruit_NeoPixel.h>

#define BUTTON_PIN   2    // Digital IO pin connected to the button.  This will be
                          // driven with a pull-up resistor so the switch should
                          // pull the pin to ground momentarily.  On a high -> low
                          // transition the button press logic will execute.

#define PIXEL_PIN    6    // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT 1

// Parameter 1 = number of pixels in strip,  neopixel stick has 8
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream, correct for neopixel stick
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip), correct for neopixel stick
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

bool oldState = HIGH;
int showType = 0;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  // Get current button state.
  bool newState = digitalRead(BUTTON_PIN);
  
  // Check if state changed from high to low (button press).
  if (newState == LOW && oldState == HIGH) {
    // Short delay to debounce button.
    delay(20);
    // Check if button is still low after debounce.
    newState = digitalRead(BUTTON_PIN);
    if (newState == LOW) {
      showType++;
      if (showType > 5)
        showType=0;
      startShow(showType);
    }
  }

  // Set the last button state to the old state.
  oldState = newState;
}

void startShow(int i) {
  switch(i){
    case 0: colorWipe(strip.Color(0, 0, 0), 50);    // Black/off
            break;
    case 1: strip.setPixelColor(0, strip.Color(255, 0, 0));   //red
      strip.show();
      break;
    case 2: strip.setPixelColor(0, strip.Color(0, 255, 0));    //green
      strip.show();
      break;
    case 3: strip.setPixelColor(0, strip.Color(0, 0, 255));   //blue
      strip.show();
      break;
    case 4: strip.setPixelColor(0, strip.Color(255, 255, 255));   //white
      strip.show();
      break;
    case 5: rainbowCycle(20);
            break;

  }
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
      delay(wait);
  }
}



// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}


// 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) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if(WheelPos < 170) {
    WheelPos -= 85;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
}

I wouldn't use that. You would need to give it a function that checks for both a button press and uses millis() to check if a period has elapsed. Even then, it would allow delay() to be removed, but it would not break the loop containing that delay(), so the pattern change would not be instant, you would still see it completing the loop at maximum speed. You could add even more code to break the loop containing the delay() if the button is pressed. That would give you instant pattern changes. But making all those changes would leave you with code that is more complex, and more ugly, than re-writing the patterns to not use delay() in the first place.

I can see you updated your code to remove colorWipe() in most places, but there is still one left. As I explained, with only a single pixel, colorWipe() is pointless. You should remove it entirely.

i just dont know how to write it to use millis and cooperate with the neopixel library.

ok so i did some digging online and found this code

modified it to this

#define PINforControl   7 // pin connected to the small NeoPixels strip
#define NUMPIXELS1      1 // number of LEDs on second strip

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS1, PINforControl, NEO_GRB + NEO_KHZ800);

unsigned long patternInterval = 20 ; // time between steps in the pattern
unsigned long lastUpdate = 0 ; // for millis() when last update occoured
unsigned long intervals [] = { 20, 20, 50, 100 } ; // speed for each pattern
const byte button = 2; // pin to connect button switch to between pin and ground

void setup() {
  strip.begin(); // This initializes the NeoPixel library.
  wipe(); // wipes the LED buffers
  pinMode(button, INPUT_PULLUP); // change pattern button
}

void loop() {
  static int pattern = 0, lastReading;
  int reading = digitalRead(button);
  if(lastReading == HIGH && reading == LOW){
    pattern++ ; // change pattern number
    if(pattern > 5) pattern = 0; // wrap round if too big
    patternInterval = intervals[pattern]; // set speed for this pattern
    wipe(); // clear out the buffer 
    delay(50); // debounce delay
  }
  lastReading = reading; // save for next time

if(millis() - lastUpdate > patternInterval) updatePattern(pattern);
}

void  updatePattern(int pat){ // call the pattern currently being created
  switch(pat) {
    case 0: strip.setPixelColor(0, strip.Color(0, 0, 0));   //off
      strip.show();
    case 1: strip.setPixelColor(0, strip.Color(255, 255, 255));   //white
      strip.show();
      break;
    case 2: strip.setPixelColor(0, strip.Color(255, 0, 0));    //red
      strip.show();
      break;
    case 3: strip.setPixelColor(0, strip.Color(0, 255, 0));   //green
      strip.show();
      break;
    case 4: strip.setPixelColor(0, strip.Color(0, 0, 255));   //blue
      strip.show();
      break;
    case 5: rainbowCycle();
            break;
  }  
}


void rainbowCycle() { // modified from Adafruit example to make it a state machine
  static uint16_t j=0;
    for(int i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
  j++;
  if(j >= 256*5) j=0;
  lastUpdate = millis(); // time for next change to the display
}


void wipe(){ // clear all LEDs
     for(int i=0;i<strip.numPixels();i++){
       strip.setPixelColor(i, strip.Color(0,0,0)); 
       }
}

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

however, when i upload it to aduino uno i get this happen, each line represents a button press.

right away they start on white (should be off)
white increases in brightness
red
green
stays on green
stays on green
back to beginning

so i dont know whats going on. i cant see whats happening in the code to make it react this way

Put a pixels.show() in setup() and add a 10K pull-down resistor to pin 7. The pixels may be picking up random data before strip.begin() is called.

That will be pattern 1.

Could be because your intervals array isn't long enough.

unsigned long intervals [] = { 20, 20, 50, 100 } ; 

You have 6 patterns but only 4 entries in the array. Not sure why you bothered with this anyway, as only one of your patterns is animated, the others are fixed colours and don't need to be updated.

No break; at the end of case 0 so the code falls through and executes the code for case 1

ok so i took mike cooks original code for neopixels without delay

ive managed to get it to work up to the point of having the fade effect, red, green, blue static lights, cycling back around to fade, however when adding a case to have solid white, it just stays on red and you have to press the button twice and it will go back to fade (so basically, the colour isnt changing from red to white)

also if i add a case for all off, so set to 0, 0, 0, 0, it jams up on that button press.

helibob i had noticed that. once corrected that part functioned properly, but i also realised that the code above was designed for several rings of neopixels,

heres the newest version, if one of you guys would be so kind as to highlight where its going wrong for white and off, i'd be grateful, its almost there, just those 2 cases to get funcitoning.

// StrandTest from AdaFruit implemented as a state machine
// pattern change by push button
// By Mike Cook Jan 2016

#define PINforControl   7 // pin connected to the small NeoPixels strip
#define NUMPIXELS1      1 // number of LEDs on strip

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS1, PINforControl, NEO_GRB + NEO_KHZ800);

unsigned long patternInterval = 20 ; // time between steps in the pattern
unsigned long lastUpdate = 0 ; // for millis() when last update occoured
unsigned long intervals [] = { 20, 20, 50, 100 } ; // speed for each pattern
const byte button = 2; // pin to connect button switch to between pin and ground

void setup() {
  strip.begin(); // This initializes the NeoPixel library.
  wipe(); // wipes the LED buffers
  pinMode(button, INPUT_PULLUP); // change pattern button
}

void loop() {
  static int pattern = 0, lastReading;
  int reading = digitalRead(button);
  if(lastReading == HIGH && reading == LOW){
    pattern++ ; // change pattern number
    if(pattern > 4) pattern = 0; // wrap round if too big
    patternInterval = intervals[pattern]; // set speed for this pattern
    wipe(); // clear out the buffer 
    delay(50); // debounce delay
  }
  lastReading = reading; // save for next time

if(millis() - lastUpdate > patternInterval) updatePattern(pattern);
}

void  updatePattern(int pat){ // call the pattern currently being created
  switch(pat) {
    case 0:
        rainbow(); 
        break;
    case 1: 
        colorWipe(strip.Color(0, 0, 255)); // blue
         break;
    case 2:
        colorWipe(strip.Color(0, 255, 0)); // green
         break;
    case 3:
         colorWipe(strip.Color(255, 0, 0)); // red
         break;
    case 4:
         colorWipe(strip.Color(175, 175, 175)); // white
         break;
    case 5:
         colorWipe(strip.Color(0, 0, 0)); // off
         break;
  }  
}

void rainbow() { // modified from Adafruit example to make it a state machine
  static uint16_t j=0;
    for(int i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
     j++;
  if(j >= 256) j=0;
  lastUpdate = millis(); // time for next change to the display
  
}


void colorWipe(uint32_t c) { // modified from Adafruit example to make it a state machine
  static int i =0;
    strip.setPixelColor(i, c);
    strip.show();
  i++;
  if(i >= strip.numPixels()){
    i = 0;
    wipe(); // blank out strip
  }
  lastUpdate = millis(); // time for next change to the display
}


void wipe(){ // clear all LEDs
     for(int i=0;i<strip.numPixels();i++){
       strip.setPixelColor(i, strip.Color(0,0,0)); 
       }
}

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

not too fussed about using "colorwipe" instead of setcolor

im looking at the "intervals" area now

it works, i had to add 2 more interval perameters