0

I am trying to make a particular pixel in a neopixel strip, turn green, red or blue depending which button has been pressed and to stay on until pressed off again (like a toggle), but currently when I press one of the buttons it flashes the correct colour when button is pressed down but isn't acting as a toggle switch and then goes to a white light.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinke
#endif

#define BUTTON_PIN1  2
#define BUTTON_PIN2  10
#define BUTTON_PIN3  11
#define PIXEL_PIN    6  // Digital pin 6 connected to the NeoPixels.

#define PIXEL_COUNT 13  // Number of NeoPixels

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

boolean oldState1 = HIGH;
boolean newState1 = HIGH;

boolean toggle1 = LOW;

boolean oldState2 = HIGH;
boolean newState2 = HIGH;

boolean toggle2 = LOW;


boolean oldState3 = HIGH;
boolean newState3 = HIGH;

boolean toggle3 = LOW;


void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN1, INPUT_PULLUP);
pinMode(BUTTON_PIN2, INPUT_PULLUP);
pinMode(BUTTON_PIN3, INPUT_PULLUP);
strip.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip.show();  // Initialize all pixels to 'off'
}

void loop() {
updateButtonState1();
updateButtonState2();
updateButtonState3();


}

void updateButtonState1() {

 // Get current button state.
 newState1 = digitalRead(BUTTON_PIN1);

 if ((newState1 == LOW) && (oldState1 == HIGH)) {
 delay(50);
 newState1 = digitalRead(BUTTON_PIN1);
 if (newState1 == LOW) {
   toggle1 = !toggle1;
  }
 }
 oldState1 = newState1;

if (toggle1 == HIGH) {
strip.setPixelColor(2, 245, 15, 15); //electrical/fire hazard (red)
} else {
strip.setPixelColor(2, 0, 0, 0);
}
strip.show(); // Update strip with new contents
}

void updateButtonState2() {

// Get current button state.
 newState2 = digitalRead(BUTTON_PIN2);

if ((newState2 == LOW) && (oldState2 == HIGH)) {
 delay(50);
 newState2 = digitalRead(BUTTON_PIN2);
 if (newState2 == LOW) {
   toggle2 = !toggle2;
   }
  }
 oldState2 = newState2;

  if (toggle2 == HIGH) {
  strip.setPixelColor(2, 13, 50, 190); //Leak (blue)
  } else {
  strip.setPixelColor(2, 0, 0, 0);
  }
 strip.show(); // Update strip with new contents
 }

 void updateButtonState3() {

 // Get current button state.
 newState3 = digitalRead(BUTTON_PIN3);
 if ((newState3 == LOW) && (oldState3 == HIGH)) {
  delay(50);
  newState3 = digitalRead(BUTTON_PIN3);
  if (newState3 == LOW) {
    toggle3 = !toggle3;  
  }
 }
 oldState3 = newState3;

 if (toggle3 == HIGH) {
 strip.setPixelColor(2, 58, 233, 65); //bins/recylcing (green)
 } else {
   strip.setPixelColor(2, 0, 0, 0);
  }
  strip.show(); // Update strip with new contents
}
  • Why do you want/need to use an array? – Paul May 12 at 12:40
  • Is the shown code not working correctly? If so, include a description in your question, how it IS actually behaving and what you expect from it. – chrisl May 12 at 12:42
0

You do not really have to use an array for this, though I do agree that it's the cleanest solution.

Here is a simplified version of your code, do mind you'll still have to do the button handling yourself (by setting buttonpressed to 'true' when the button is pressed.

Also, when adding more colors to the array, you'll have to manually adjust 'totalColors'.

void setup() {
  //Color/pixel declarations based on https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library-use
  uint32_t magenta = strip.Color(255, 0, 255);
  uint32_t greenishwhite = strip.Color(0, 64, 0, 64);

  //https://www.arduino.cc/reference/en/language/variables/data-types/array/
  uint32_t colors[] = {magenta, greenishwhite};
  unsigned char totalColors = 2;
  unsigned char currentColor = 0;
}

void loop() {
  if (buttonpressed) {
    //Change the "currentColor" index every time the button is pressed, but make it start at 0 when it reached the end.
    currentColor++;
    if (currentColor >= totalColors) {
      currentColor = 0;
    }

    //From the array of colors, pick the one with the index "currentColor" and show it.
    ledstrip.fill( colors[currentColor] , 0, strip.numPixels() - 1);
    ledstrip.show();

    buttonpressed = false; //Reset flag, so this doesn't get executed until next time button is pressed.
  }
}

You should be able to replace the first 3 lines (setting up the array) with a single:

uint32_t colors[] = {strip.Color(255, 0, 255,  strip.Color(0, 64, 0, 64)};

But I had it split up to better show the idea of the array.

Alternatively you could do:

switch(currentColor){
  case 0:
    //Color RED
  break;
  case 1:
    //Color GREEN
  break;
  case 2:
    //Color BLAUW
  break;
}
  • Thank you so much! Where in the code do I set up the buttonpressed as true ? I thought potentially an array was the best way to do it as after this I would like to set it up so that first in can be input which neopixel to turn on with one set of buttons then which colour (which is the part this code is trying to address) – Georgia Cottington May 12 at 13:22
  • It doesn't quite matter where you put "buttonPressed" to true. Though preferably before the code where it checks it. You could even swap "buttonPressed" for ”digitalRead(buttonPin)” and put a delay after changing the colours of the pixels (to avoid contact bounce to call do it multiple times for a single press). – Paul May 12 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.