Hi guys , I am far from experienced with programming / arduino. Last I tinkered around with programming was in high school (a loooong time ago).
I am trying to to use 5 single neopixels (cut from a strip and soldered) and 5 tactile buttons. All I want is for each button to cycle their respective single neopixel when pressed.
Eg. When button 1 is pressed , cycle Neopixel 1
When button 2 is pressed , cycle Neopixel 2
The cycle will involve color change and then the Rainbow effect on the last case.
The wiring is pretty easy and I don't have any issue there but the code is confusing.
I started off by using the Adafruite example (Button cycler) and I am able to get this working with 1 button and 1 neopixel.
I understand that I have to define the other buttons and other neopixels but what do I do from there?
Should I copy and paste the loops?
Here is my current code
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Digital IO pin connected to the button. This will be driven with a
// pull-up resistor so the switch pulls the pin to ground momentarily.
// On a high -> low transition the button press logic will execute.
#define BUTTON_PIN 2
#define BUTTON_PIN2 3
#define BUTTON_PIN3 4
#define BUTTON_PIN4 5
#define BUTTON_PIN5 6
#define PIXEL_PIN1 8 // Digital IO pin connected to the NeoPixels.
#define PIXEL_PIN2 9
#define PIXEL_PIN3 10
#define PIXEL_PIN4 11
#define PIXEL_PIN5 12 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 1 // Number of NeoPixels
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(PIXEL_COUNT, PIXEL_PIN2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip3(PIXEL_COUNT, PIXEL_PIN3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip4(PIXEL_COUNT, PIXEL_PIN4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip5(PIXEL_COUNT, PIXEL_PIN5, NEO_GRB + NEO_KHZ800);
// 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)
boolean oldState = HIGH;
int mode = 0; // Currently-active animation mode, 0-9
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
// Get current button state.
boolean 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) { // Yes, still low
if (++mode > 8) mode = 0; // Advance to next mode, wrap around after #8
switch (mode) { // Start the new animation...
case 0:
colorWipe(strip.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe(strip.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe(strip.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe(strip.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe(strip.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe(strip.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe(strip.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe(strip.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe(strip.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe(strip.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow(10);
break;
}
}
}
// Set the last-read button state to the old state.
oldState = newState;
}
void colorWipe(uint32_t color, int wait) {
for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
I assume you want ultimately to have five different effects going on five different strips.
It's not entirely unusual to do this with five separate strips on five pins, in fact it may be easier conceptually.
But, and as one might say, this is a big but, you cannot base this on the current got-one-working code because
delay(wait);
literally halts all progress of any type.
You need to learn how to do more than one thing at once. And we are going to enjoy helping you see how to learn to do that.
For now, google
Arduino blink without delay
Arduino two things at once
and
Arduino finite state machine
Might as well
Arduino state change detection
Curl up and spend some serious time. If nothing makes any sense, come back and say so, you may need to up your game with more basic programming ideas and how they are expressed in C/C++ in the Arduino world. And we are going to enjoy helping you see how to do that.
Srsly, this stuff is fun; hard before it is easy and TBH I wish I had to learn it all over again, the reward was worth the slog.
Thank you all for the info. I am making a little night light toy for my kids. It uses 5 single neopixels (V+/Gnd/Data) and a button for each one to cycle through the colors (Red / Green etc). I was just hoping there was an easy way to sorta link each button to the single neopixel and then cycle that neopixel. Only one button will be pressed at a time.
A heartbeat LED (the onboard L LED) toggles every 500ms to show if there is any code blocking in the sketch.
Homework, you are to study how arrays work and apply what you learn to this sketch.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define NUM_BUTTONS 5
#define PIXEL_COUNT 5
//Button Pins
const uint8_t buttonPins[NUM_BUTTONS] = {2, 3, 4, 5, 6};
const byte PIXEL_PIN = 8;
const byte heartbeatLED = 13;
//Create ONE NeoPixel Strip
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
boolean lastState[NUM_BUTTONS];
int mode[NUM_BUTTONS];
unsigned long heartbeatTime;
unsigned long heartbeatInterval = 500ul;
// s e t u p ( )
//================================================^================================================
//
void setup()
{
pinMode(heartbeatLED, OUTPUT);
for (int i = 0; i < NUM_BUTTONS; i++)
{
pinMode(buttonPins[i], INPUT_PULLUP);
lastState[i] = HIGH;
mode[i] = 0;
}
strip.begin();
strip.clear();
strip.show();
strip.setBrightness(50);
} //END of setup()
// l o o p ( )
//================================================^================================================
//
void loop()
{
//======================================================================== T I M E R heartbeatLED
//Is it time to toggle the heartbeat LED ?
if (millis() - heartbeatTime >= heartbeatInterval)
{
// Restart this TIMER.
heartbeatTime = millis();
// This gives us an indication if our sketch is non-blocking.
// Toggle the heartbeat LED.
digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
}
//======================================================================== Handle Pixel Strip
for (int i = 0; i < NUM_BUTTONS; i++)
{
boolean newState = digitalRead(buttonPins[i]);
if ((newState == LOW) && (lastState[i] == HIGH))
{
delay(20); // debounce
newState = digitalRead(buttonPins[i]);
if (newState == LOW)
{
if (++mode[i] > 9) mode[i] = 0;
switch (mode[i])
{
case 0: setPixelColor(i, 0, 0, 0); break; // Off
case 1: setPixelColor(i, 255, 0, 0); break; // Red
case 2: setPixelColor(i, 0, 255, 0); break; // Green
case 3: setPixelColor(i, 0, 0, 255); break; // Blue
case 4: setPixelColor(i, 255, 255, 255); break; // White
case 5: setPixelColor(i, 255, 255, 0); break; // Yellow
case 6: setPixelColor(i, 255, 25, 125); break; // Hot Pink
case 7: setPixelColor(i, 255, 150, 50); break; // Warm White
case 8: setPixelColor(i, 255, 65, 255); break; // Purple
case 9: setPixelColor(i, 50, 200, 255); break; // Light Blue
}
}
}
lastState[i] = newState;
}
} //END of loop()
// s e t P i x e l C o l o r ( )
//================================================^================================================
//
void setPixelColor(int pixelNumber, int r, int g, int b)
{
strip.setPixelColor(pixelNumber, strip.Color(r, g, b));
strip.show();
} //END of setPixelColor()
TBC - you want five pixels, each doing a selected effect all appearing to do at the same time but
you only expect one button to be pressed at a time.
This is different to "radio buttons", where only one pixel does anything, the one whose button was last pressed, which press might not only select the performing pixel, if it was not already, but step it along through multiple available effects.
Part of making this easier is being 100 percent clear about exactly how it is to work.
True of any project, no matter how trivial.
It may be easier to use five pixels hanging off one pin, yes I said different earlier. Your current specifications are in an interesting area, ripe for multiple approaches.
Nevertheless all the stuff I pointed you at will never be a waste of the time you can give it, and would certainly expose a well-worn path to victory.
I got it working. I just did a bit of copy and paste. Only problem now is the Nano gets super hot after about 10 mins. Powering it with a powerbank for now.
I have used no resistors because I it is basically 5 neopixels (cut from strip). I have a feeling it may be because I am loading everything on to 1 Gnd pin?
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Digital IO pin connected to the button. This will be driven with a
// pull-up resistor so the switch pulls the pin to ground momentarily.
// On a high -> low transition the button press logic will execute.
#define BUTTON_PIN 2
#define BUTTON_PIN2 3
#define BUTTON_PIN3 4
#define BUTTON_PIN4 5
#define BUTTON_PIN5 6
#define PIXEL_PIN1 8 // Digital IO pin connected to the NeoPixels.
#define PIXEL_PIN2 9
#define PIXEL_PIN3 10
#define PIXEL_PIN4 11
#define PIXEL_PIN5 12 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 1 // Number of NeoPixels
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(PIXEL_COUNT, PIXEL_PIN2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip3(PIXEL_COUNT, PIXEL_PIN3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip4(PIXEL_COUNT, PIXEL_PIN4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip5(PIXEL_COUNT, PIXEL_PIN5, NEO_GRB + NEO_KHZ800);
// 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)
boolean oldState = HIGH;
boolean oldState2 = HIGH;
boolean oldState3 = HIGH;
boolean oldState4 = HIGH;
boolean oldState5 = HIGH;
int mode = 0; // Currently-active animation mode, 0-9
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(BUTTON_PIN2, INPUT_PULLUP);
pinMode(BUTTON_PIN3, INPUT_PULLUP);
pinMode(BUTTON_PIN4, INPUT_PULLUP);
pinMode(BUTTON_PIN5, INPUT_PULLUP);
strip.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip.show(); // Initialize all pixels to 'off'
strip2.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip2.show(); // Initialize all pixels to 'off'
strip3.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip3.show(); // Initialize all pixels to 'off'
strip4.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip4.show(); // Initialize all pixels to 'off'
strip5.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip5.show(); // Initialize all pixels to 'off'
}
void loop() {
// Get current button state.
boolean newState = digitalRead(BUTTON_PIN);
boolean newState2 = digitalRead(BUTTON_PIN2);
boolean newState3 = digitalRead(BUTTON_PIN3);
boolean newState4 = digitalRead(BUTTON_PIN4);
boolean newState5 = digitalRead(BUTTON_PIN5);
// Check if state changed from high to low (button press).
if ((newState == LOW) && (oldState == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState = digitalRead(BUTTON_PIN);
if (newState == LOW) { // Yes, still low
if (++mode > 10) mode = 0; // Advance to next mode, wrap around after #8
switch (mode) { // Start the new animation...
case 0:
colorWipe(strip.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe(strip.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe(strip.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe(strip.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe(strip.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe(strip.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe(strip.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe(strip.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe(strip.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe(strip.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow(10);
break;
}
}
}
// Check if state changed from high to low (button press).
if ((newState2 == LOW) && (oldState2 == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState2 = digitalRead(BUTTON_PIN2);
if (newState2 == LOW) { // Yes, still low
if (++mode > 10) mode = 0; // Advance to next mode, wrap around after #8
switch (mode) { // Start the new animation...
case 0:
colorWipe2(strip2.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe2(strip2.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe2(strip2.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe2(strip2.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe2(strip2.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe2(strip2.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe2(strip2.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe2(strip2.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe2(strip2.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe2(strip2.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow2(10);
break;
}
}
}
// Check if state changed from high to low (button press).
if ((newState3 == LOW) && (oldState3 == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState3 = digitalRead(BUTTON_PIN3);
if (newState3 == LOW) { // Yes, still low
if (++mode > 10) mode = 0; // Advance to next mode, wrap around after #8
switch (mode) { // Start the new animation...
case 0:
colorWipe3(strip3.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe3(strip3.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe3(strip3.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe3(strip3.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe3(strip3.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe3(strip3.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe3(strip3.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe3(strip3.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe3(strip3.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe3(strip3.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow3(10);
break;
}
}
}
// Check if state changed from high to low (button press).
if ((newState4 == LOW) && (oldState4 == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState4 = digitalRead(BUTTON_PIN4);
if (newState4 == LOW) { // Yes, still low
if (++mode > 10) mode = 0; // Advance to next mode, wrap around after #8
switch (mode) { // Start the new animation...
case 0:
colorWipe4(strip4.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe4(strip4.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe4(strip4.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe4(strip4.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe4(strip4.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe4(strip4.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe4(strip4.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe4(strip4.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe4(strip4.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe4(strip4.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow4(10);
break;
}
}
}
// Check if state changed from high to low (button press).
if ((newState5 == LOW) && (oldState5 == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState5 = digitalRead(BUTTON_PIN5);
if (newState5 == LOW) { // Yes, still low
if (++mode > 10) mode = 0; // Advance to next mode, wrap around after #8
switch (mode) { // Start the new animation...
case 0:
colorWipe5(strip5.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe5(strip5.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe5(strip5.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe5(strip5.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe5(strip5.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe5(strip5.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe5(strip5.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe5(strip5.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe5(strip5.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe5(strip5.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow5(10);
break;
}
}
}
// Set the last-read button state to the old state.
oldState = newState;
oldState2 = newState2;
oldState3 = newState3;
oldState4 = newState4;
oldState5 = newState5;
}
void colorWipe(uint32_t color, int wait) {
for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void colorWipe2(uint32_t color, int wait) {
for (int i = 0; i < strip2.numPixels(); i++) { // For each pixel in strip...
strip2.setPixelColor(i, color); // Set pixel's color (in RAM)
strip2.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void colorWipe3(uint32_t color, int wait) {
for (int i = 0; i < strip3.numPixels(); i++) { // For each pixel in strip...
strip3.setPixelColor(i, color); // Set pixel's color (in RAM)
strip3.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void colorWipe4(uint32_t color, int wait) {
for (int i = 0; i < strip4.numPixels(); i++) { // For each pixel in strip...
strip4.setPixelColor(i, color); // Set pixel's color (in RAM)
strip4.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void colorWipe5(uint32_t color, int wait) {
for (int i = 0; i < strip5.numPixels(); i++) { // For each pixel in strip...
strip5.setPixelColor(i, color); // Set pixel's color (in RAM)
strip5.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void rainbow2(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip2.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip2.numPixels());
strip2.setPixelColor(i, strip2.gamma32(strip2.ColorHSV(pixelHue)));
}
strip2.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void rainbow3(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip3.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip3.numPixels());
strip3.setPixelColor(i, strip3.gamma32(strip3.ColorHSV(pixelHue)));
}
strip3.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void rainbow4(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip4.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip4.numPixels());
strip4.setPixelColor(i, strip4.gamma32(strip4.ColorHSV(pixelHue)));
}
strip4.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void rainbow5(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip5.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip5.numPixels());
strip5.setPixelColor(i, strip5.gamma32(strip5.ColorHSV(pixelHue)));
}
strip5.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
If you have all five pixels at maximum brightness you could be trying to draw 300 mA from the 5 volt pin, which is probably time to think about supplying power differently.
But on USB, that should not result in super hot.
You could add a global brightness call in setup() to limit the overall current as a test. Set it to 1/3 brightness, the Arduino might get warmish, at worst.
Shoot us some good pictures all over your project in its current (no pun intended) state. It feels like sumpin' else is going on over there.
If this is your only project and you happy with it, so am I.
If this is the start of real engagement with this undertaking, or hobby, whatever, your next first stop shoukd be to learn about functions, and leave to your old self the method of growing a program by copy/paste/editing something that works.
Your five of everything that started with but one could all be written as generalizations, where basically everything you had to edit woukd instead come from a single number passed to functions each of which woukd do the thing to any of 0 .. N - 1 of your buttons or pixels.
So the code would be ~20 percent of its current bulk, and woukd become easier to fix, modify or enhance, because… you woukd not need to visit such changes to every one of N basically identical code sections.
Oh, and arrays, as @LarryD says. They dovetail well, usually we say when you are making new variables by appending a digit or letter to differentiate among them, it's time to start knowing about arrays.
I am not known to post much complete here-ya-go code, and I am not convinced that is of real value to do and say "look this over".
So I don't write code and do that. And I did not just now, but I did take just a few minutes to create the below, which I do hope you look over and find of some value.
AI. Untested but in my experience the kind of thing it can get right with a good prompt.
/*******************************************************
GLOBAL INCLUDES
********************************************************/
#include <Adafruit_NeoPixel.h>
/*******************************************************
GLOBAL CONFIGURATION CONSTANTS
********************************************************/
#define NUM_PIXELS 1 // Each strip is a single NeoPixel
#define NUM_BUTTONS 5 // Total button/pixel pairs
#define NUM_MODES 10 // 10 colour modes (0–9)
/*******************************************************
HARDWARE PIN DEFINITIONS
(Button N controls Pixel N)
********************************************************/
const uint8_t buttonPins[NUM_BUTTONS] = {2, 3, 4, 5, 6};
const uint8_t pixelPins[NUM_BUTTONS] = {8, 9, 10, 11, 12};
/*******************************************************
NEOPIXEL OBJECTS
(Each pixel is on its own separate pin)
********************************************************/
Adafruit_NeoPixel strips[NUM_BUTTONS] = {
Adafruit_NeoPixel(NUM_PIXELS, pixelPins[0], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUM_PIXELS, pixelPins[1], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUM_PIXELS, pixelPins[2], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUM_PIXELS, pixelPins[3], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(NUM_PIXELS, pixelPins[4], NEO_GRB + NEO_KHZ800)
};
/*******************************************************
STATE TRACKING ARRAYS
(Each button/pixel has independent state)
********************************************************/
uint8_t mode[NUM_BUTTONS] = {0}; // Current colour index
uint8_t oldState[NUM_BUTTONS] = {HIGH}; // Previous button state
uint8_t newState[NUM_BUTTONS] = {HIGH}; // Current button state
/*******************************************************
COLOUR TABLE
Replaces the old switch/case structure.
Mode index selects directly from this array.
********************************************************/
uint32_t colors[NUM_MODES] = {
Adafruit_NeoPixel::Color(0, 0, 0), // 0 - Off
Adafruit_NeoPixel::Color(255, 0, 0), // 1 - Red
Adafruit_NeoPixel::Color(0, 255, 0), // 2 - Green
Adafruit_NeoPixel::Color(0, 0, 255), // 3 - Blue
Adafruit_NeoPixel::Color(255, 255, 255), // 4 - White
Adafruit_NeoPixel::Color(255, 255, 0), // 5 - Yellow
Adafruit_NeoPixel::Color(255, 25, 125), // 6 - Hot Pink
Adafruit_NeoPixel::Color(255, 150, 50), // 7 - Warm White
Adafruit_NeoPixel::Color(255, 65, 255), // 8 - Purple
Adafruit_NeoPixel::Color(50, 200, 255) // 9 - Light Blue
};
/*******************************************************
GENERAL BUTTON HANDLER FUNCTION
- Call handleButton(i) from loop()
- Button N controls Pixel N
- Uses simple debounce delay (acceptable here since
each pixel is independent and no long animations
are running)
********************************************************/
void handleButton(uint8_t index) {
newState[index] = digitalRead(buttonPins[index]);
// Detect HIGH → LOW transition (button press)
if ((newState[index] == LOW) && (oldState[index] == HIGH)) {
delay(20); // Simple debounce
newState[index] = digitalRead(buttonPins[index]);
if (newState[index] == LOW) {
// Advance mode and wrap around
mode[index]++;
if (mode[index] >= NUM_MODES) {
mode[index] = 0;
}
// Apply selected colour to this pixel
strips[index].setPixelColor(0, colors[mode[index]]);
strips[index].show();
}
}
// Save state for next pass
oldState[index] = newState[index];
}
The only thing I would change is to make it clear that here N would run from 0 to 4 to designate which of the five button/pixels we talking about.
And probably make all the comments a bit quieter, if I even left them in at all.
For the curious,
my prompt:
The inquirer copy/paste/edited her code to handle not one swtich and neopixel but five. Leave the neopixels on separate pins (individual pixels, so no wiring win to make the 5 be one strip) and turn this specific to pixel 5 code into general code for button N to control pixel N. Change out the switch/case to select colours from an array instead of the literal way it needs to be done now as case code. Leave off the one case that calls a different effect. Publish all the global variables needed to inform the new function andthe new function itself. Do not write a complete sketch; let's leave something over for her to work out.
I also pasted one of the five code blocks. It is worth saying I did not supply the entire sketch, you can see that it works out the same pin numbers from the code section I did supply.
I don't srsly know whether I'm glad I am old or not. It is clear that computer programming is already becoming quite a different undertaking.
HTH
added: I'm not liking the button handling, but it probably works OK in this context.
Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.
Arduinos like the Uno and Nano are limited in total current sourced or sank by IO pins of 200 mA. It’s not a good idea to run at Max as the heat has to go somewhere.
Neopixels can draw 60 mA each, 5 at 50 is still way too much!
When I run string leds, I power them directly from an external to the board supply.
Class of 75 here but our school had a terminal with tape punch though I didn’t get that class. 4 function calculators were getting “cheap” at under $50 when min wage was $2/hr.
If you learn programming all over, you will start with a bucket of clues and concepts that can put you ahead but be prepared for the new that obsoletes some old. Work on yourself as a main project by doing lesser projects.
Use an external power supply for the WS2812B/NeoPixels and a resistor in-line with the data pin. Since you are only using one WS2812B per pin, I would say there is no need for an electrolytic capacitor to protect against power surges or sags.
Everything should be on one ground reference, so they each know where ground is.
I ran your code from Post #1. You need independent "mode" variables for each button. If I press button 1only one time, then LED 1 turns red, however, if I press button 2 only one time, LED 2 turns green (I would expect LED 2 to be red on button 2 first press). This continues for every button because only one "mode" variable exists, and is shared.
Also... and what really grinds my gears... is that you use "BUTTON_PIN2" for the second button but "BUTTON_PIN" for the first button... Why not "BUTTON_PIN1"? Anyway... I followed your non-array style of code, but put the "1" after the first variable names. AND... I added a MODE1 through MODE5 for the modes. Now, each button/led act independently.
The last mode (rainbow) is a blocking code and will not allow reading of any buttons or advancing any modes. You will need to learn about millis() and "event timing" to make this mode "non-blocking"...
#include <Adafruit_NeoPixel.h>
#define BUTTON_PIN1 2
#define BUTTON_PIN2 3
#define BUTTON_PIN3 4
#define BUTTON_PIN4 5
#define BUTTON_PIN5 6
#define PIXEL_PIN1 8 // Digital IO pin connected to the NeoPixels.
#define PIXEL_PIN2 9
#define PIXEL_PIN3 10
#define PIXEL_PIN4 11
#define PIXEL_PIN5 12 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 1 // Number of NeoPixels
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip1(PIXEL_COUNT, PIXEL_PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(PIXEL_COUNT, PIXEL_PIN2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip3(PIXEL_COUNT, PIXEL_PIN3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip4(PIXEL_COUNT, PIXEL_PIN4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip5(PIXEL_COUNT, PIXEL_PIN5, NEO_GRB + NEO_KHZ800);
boolean oldState1 = HIGH;
boolean oldState2 = HIGH;
boolean oldState3 = HIGH;
boolean oldState4 = HIGH;
boolean oldState5 = HIGH;
int mode1 = 0; // Currently-active animation mode, 0-9
int mode2 = 0;
int mode3 = 0;
int mode4 = 0;
int mode5 = 0;
void setup() {
pinMode(BUTTON_PIN1, INPUT_PULLUP);
pinMode(BUTTON_PIN2, INPUT_PULLUP);
pinMode(BUTTON_PIN3, INPUT_PULLUP);
pinMode(BUTTON_PIN4, INPUT_PULLUP);
pinMode(BUTTON_PIN5, INPUT_PULLUP);
strip1.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip1.show(); // Initialize all pixels to 'off'
strip2.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip2.show(); // Initialize all pixels to 'off'
strip3.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip3.show(); // Initialize all pixels to 'off'
strip4.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip4.show(); // Initialize all pixels to 'off'
strip5.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip5.show(); // Initialize all pixels to 'off'
}
void loop() {
// Get current button state.
boolean newState1 = digitalRead(BUTTON_PIN1);
boolean newState2 = digitalRead(BUTTON_PIN2);
boolean newState3 = digitalRead(BUTTON_PIN3);
boolean newState4 = digitalRead(BUTTON_PIN4);
boolean newState5 = digitalRead(BUTTON_PIN5);
// Check if state changed from high to low (button press).
if ((newState1 == LOW) && (oldState1 == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState1 = digitalRead(BUTTON_PIN1);
if (newState1 == LOW) { // Yes, still low
if (++mode1 > 10) mode1 = 0; // Advance to next mode, wrap around after #8
switch (mode1) { // Start the new animation...
case 0:
colorWipe(strip1.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe(strip1.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe(strip1.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe(strip1.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe(strip1.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe(strip1.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe(strip1.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe(strip1.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe(strip1.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe(strip1.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow(10);
break;
}
}
}
// Check if state changed from high to low (button press).
if ((newState2 == LOW) && (oldState2 == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState2 = digitalRead(BUTTON_PIN2);
if (newState2 == LOW) { // Yes, still low
if (++mode2 > 10) mode2 = 0; // Advance to next mode, wrap around after #8
switch (mode2) { // Start the new animation...
case 0:
colorWipe2(strip2.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe2(strip2.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe2(strip2.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe2(strip2.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe2(strip2.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe2(strip2.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe2(strip2.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe2(strip2.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe2(strip2.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe2(strip2.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow2(10);
break;
}
}
}
// Check if state changed from high to low (button press).
if ((newState3 == LOW) && (oldState3 == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState3 = digitalRead(BUTTON_PIN3);
if (newState3 == LOW) { // Yes, still low
if (++mode3 > 10) mode3 = 0; // Advance to next mode, wrap around after #8
switch (mode3) { // Start the new animation...
case 0:
colorWipe3(strip3.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe3(strip3.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe3(strip3.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe3(strip3.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe3(strip3.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe3(strip3.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe3(strip3.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe3(strip3.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe3(strip3.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe3(strip3.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow3(10);
break;
}
}
}
// Check if state changed from high to low (button press).
if ((newState4 == LOW) && (oldState4 == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState4 = digitalRead(BUTTON_PIN4);
if (newState4 == LOW) { // Yes, still low
if (++mode4 > 10) mode4 = 0; // Advance to next mode, wrap around after #8
switch (mode4) { // Start the new animation...
case 0:
colorWipe4(strip4.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe4(strip4.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe4(strip4.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe4(strip4.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe4(strip4.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe4(strip4.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe4(strip4.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe4(strip4.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe4(strip4.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe4(strip4.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow4(10);
break;
}
}
}
// Check if state changed from high to low (button press).
if ((newState5 == LOW) && (oldState5 == HIGH)) {
delay(20);
// Check if button is still low after debounce.
newState5 = digitalRead(BUTTON_PIN5);
if (newState5 == LOW) { // Yes, still low
if (++mode5 > 10) mode5 = 0; // Advance to next mode, wrap around after #8
switch (mode5) { // Start the new animation...
case 0:
colorWipe5(strip5.Color(0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe5(strip5.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe5(strip5.Color(0, 255, 0), 50); // Green
break;
case 3:
colorWipe5(strip5.Color(0, 0, 255), 50); // Blue
break;
case 4:
colorWipe5(strip5.Color(255, 255, 255), 50); // White
break;
case 5:
colorWipe5(strip5.Color(255, 255, 0), 50); // Yellow
break;
case 6:
colorWipe5(strip5.Color(255, 25, 125), 50); // Hot Pink
break;
case 7:
colorWipe5(strip5.Color(255, 150, 50), 50); // Warm White
break;
case 8:
colorWipe5(strip5.Color(255, 65, 255), 50); // Purple
break;
case 9:
colorWipe5(strip5.Color(50, 200, 255), 50); // Light Blue
break;
case 10:
rainbow5(10);
break;
}
}
}
// Set the last-read button state to the old state.
oldState1 = newState1;
oldState2 = newState2;
oldState3 = newState3;
oldState4 = newState4;
oldState5 = newState5;
}
void colorWipe(uint32_t color, int wait) {
for (int i = 0; i < strip1.numPixels(); i++) { // For each pixel in strip...
strip1.setPixelColor(i, color); // Set pixel's color (in RAM)
strip1.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void colorWipe2(uint32_t color, int wait) {
for (int i = 0; i < strip2.numPixels(); i++) { // For each pixel in strip...
strip2.setPixelColor(i, color); // Set pixel's color (in RAM)
strip2.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void colorWipe3(uint32_t color, int wait) {
for (int i = 0; i < strip3.numPixels(); i++) { // For each pixel in strip...
strip3.setPixelColor(i, color); // Set pixel's color (in RAM)
strip3.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void colorWipe4(uint32_t color, int wait) {
for (int i = 0; i < strip4.numPixels(); i++) { // For each pixel in strip...
strip4.setPixelColor(i, color); // Set pixel's color (in RAM)
strip4.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
void colorWipe5(uint32_t color, int wait) {
for (int i = 0; i < strip5.numPixels(); i++) { // For each pixel in strip...
strip5.setPixelColor(i, color); // Set pixel's color (in RAM)
strip5.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip1.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip1.numPixels());
strip1.setPixelColor(i, strip1.gamma32(strip1.ColorHSV(pixelHue)));
}
strip1.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void rainbow2(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip2.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip2.numPixels());
strip2.setPixelColor(i, strip2.gamma32(strip2.ColorHSV(pixelHue)));
}
strip2.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void rainbow3(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip3.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip3.numPixels());
strip3.setPixelColor(i, strip3.gamma32(strip3.ColorHSV(pixelHue)));
}
strip3.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void rainbow4(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip4.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip4.numPixels());
strip4.setPixelColor(i, strip4.gamma32(strip4.ColorHSV(pixelHue)));
}
strip4.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
void rainbow5(int wait) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
for (int i = 0; i < strip5.numPixels(); i++) { // For each pixel in strip...
int pixelHue = firstPixelHue + (i * 65536L / strip5.numPixels());
strip5.setPixelColor(i, strip5.gamma32(strip5.ColorHSV(pixelHue)));
}
strip5.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
I encourage using arrays to simplify the addressing of devices (buttons, LEDs, modes).
[edit] while messing with arrays for this sketch, I noticed calculations like i * anything and i < strip#.numPixels(); i++ boiled down to "0" (zero) because there is only one neopixel, and its index number is "0". That makes the blocking rainbow() function (which uses delay()) looks like this:
void rainbow(int wait, int s) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
strip[s].setPixelColor(0, strip[s].gamma32(strip[s].ColorHSV(firstPixelHue)));
strip[s].show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
However; even though each button can independently put an individual neopixel into any of the nine colors, the fact that these functions are called one time, and not continuously called, stops a non-blocking rainbow() function from changing more than one step. Maybe someone who can really program can figure it out. I can not.
using arrays
// https://forum.arduino.cc/t/independent-neopixel-with-independent-buttons-single-arduino-nano/1430695/15
#include <Adafruit_NeoPixel.h>
int BUTTON_PIN[] = {2, 3, 4, 5, 6};
int PIXEL_PIN[] = {8, 9, 10, 11, 12};
#define PIXEL_COUNT 1 // Number of NeoPixels
Adafruit_NeoPixel strip[] = { // array of five objects
Adafruit_NeoPixel (PIXEL_COUNT, PIXEL_PIN[0], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel (PIXEL_COUNT, PIXEL_PIN[1], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel (PIXEL_COUNT, PIXEL_PIN[2], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel (PIXEL_COUNT, PIXEL_PIN[3], NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel (PIXEL_COUNT, PIXEL_PIN[4], NEO_GRB + NEO_KHZ800),
};
bool oldState[] = {HIGH, HIGH, HIGH, HIGH, HIGH}, newState[5];
int mode[] = {0, 0, 0, 0, 0};
long firstPixelHue;
unsigned long timer[5], timeout[] = {10, 10, 10, 10, 10};
void setup() {
Serial.begin(115200);
for (byte i = 0; i < 5; i++) {
pinMode(BUTTON_PIN[i], INPUT_PULLUP);
strip[i].begin();
strip[i].show();
}
}
void loop() {
// Get current button state.
for (byte i = 0; i < 5; i++) {
newState[i] = digitalRead(BUTTON_PIN[i]);
// Check if state changed from high to low (button press).
if ((newState[i] == LOW) && (oldState[i] == HIGH)) {
delay(20); // debounce
// Check if button is still low after debounce.
newState[i] = digitalRead(BUTTON_PIN[i]);
if (newState[i] == LOW) { // Yes, still low
if (++mode[i] > 10)
mode[i] = 0; // Advance to next mode, wrap around after #8
switch (mode[i]) { // Start the new animation...
case 0:
colorWipe(strip[i].Color(0, 0, 0), 50, i); // Black/off
break;
case 1:
colorWipe(strip[i].Color(255, 0, 0), 50, i); // Red
break;
case 2:
colorWipe(strip[i].Color(0, 255, 0), 50, i); // Green
break;
case 3:
colorWipe(strip[i].Color(0, 0, 255), 50, i); // Blue
break;
case 4:
colorWipe(strip[i].Color(255, 255, 255), 50, i); // White
break;
case 5:
colorWipe(strip[i].Color(255, 255, 0), 50, i); // Yellow
break;
case 6:
colorWipe(strip[i].Color(255, 25, 125), 50, i); // Hot Pink
break;
case 7:
colorWipe(strip[i].Color(255, 150, 50), 50, i); // Warm White
break;
case 8:
colorWipe(strip[i].Color(255, 65, 255), 50, i); // Purple
break;
case 9:
colorWipe(strip[i].Color(50, 200, 255), 50, i); // Light Blue
break;
case 10:
rainbow(10, i);
break;
default: break;
}
}
}
// Set the last-read button state to the old state.
oldState[i] = newState[i];
}
}
void colorWipe(uint32_t color, int wait, int s) {
for (int i = 0; i < strip[s].numPixels(); i++) { // For each pixel in strip...
strip[s].setPixelColor(i, color); // Set pixel's color (in RAM)
strip[s].show(); // Update strip to match
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait, int s) {
for (long firstPixelHue = 0; firstPixelHue < 3 * 65536; firstPixelHue += 256) {
strip[s].setPixelColor(0, strip[s].gamma32(strip[s].ColorHSV(firstPixelHue)));
strip[s].show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
// This is the timer that would make each LED color-fade, but for the one-shot call
// if (millis() - timer[s] > timeout[s]) {
// timer[s] = millis();
// if ((firstPixelHue += 256) > (3 * 65536L))
// firstPixelHue = 0;
// strip[s].setPixelColor(0, strip[s].gamma32(strip[s].ColorHSV(firstPixelHue)));
// strip[s].show(); // Update strip with new contents
// }
}
The data pin connects to a kind of shift register that gets RBG bytes and passes them along, the pixel chain is driven by supplied power. My WS fun is 2811’s and I never needed any resistor. The data pin does no driving on WS28xx, those are daisy-chain devices.
When the Arduino is powered form its own 5V source and the strip has its own 5V power source, if the Arduino is turned off with the strip turned on, there could be back feed to the Arduino's GPIO's internal diodes.
Helps prevent induced spikes in cabling from damaging the first pixel too.
You've basically solved this in a few lines. Brilliant! Thank you so much for the effort. I've tried to add the rainbow effect into your code but what is does is change the entire strip (5 neopixels) to rainbow.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define NUM_BUTTONS 5
#define PIXEL_COUNT 5
//Button Pins
const uint8_t buttonPins[NUM_BUTTONS] = {2, 3, 4, 5, 6};
const byte PIXEL_PIN = 8;
const byte heartbeatLED = 13;
//Create ONE NeoPixel Strip
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
boolean lastState[NUM_BUTTONS];
int mode[NUM_BUTTONS];
unsigned long heartbeatTime;
unsigned long heartbeatInterval = 500ul;
// s e t u p ( )
//================================================^================================================
//
void setup()
{
pinMode(heartbeatLED, OUTPUT);
for (int i = 0; i < NUM_BUTTONS; i++)
{
pinMode(buttonPins[i], INPUT_PULLUP);
lastState[i] = HIGH;
mode[i] = 0;
}
strip.begin();
strip.clear();
strip.show();
strip.setBrightness(50);
} //END of setup()
// l o o p ( )
//================================================^================================================
//
void loop()
{
//======================================================================== T I M E R heartbeatLED
//Is it time to toggle the heartbeat LED ?
if (millis() - heartbeatTime >= heartbeatInterval)
{
// Restart this TIMER.
heartbeatTime = millis();
// This gives us an indication if our sketch is non-blocking.
// Toggle the heartbeat LED.
digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
}
//======================================================================== Handle Pixel Strip
for (int i = 0; i < NUM_BUTTONS; i++)
{
boolean newState = digitalRead(buttonPins[i]);
if ((newState == LOW) && (lastState[i] == HIGH))
{
delay(20); // debounce
newState = digitalRead(buttonPins[i]);
if (newState == LOW)
{
if (++mode[i] > 10) mode[i] = 0;
switch (mode[i])
{
case 0: setPixelColor(i, 0, 0, 0); break; // Off
case 1: setPixelColor(i, 255, 0, 0); break; // Red
case 2: setPixelColor(i, 0, 255, 0); break; // Green
case 3: setPixelColor(i, 0, 0, 255); break; // Blue
case 4: setPixelColor(i, 255, 255, 255); break; // White
case 5: setPixelColor(i, 255, 255, 0); break; // Yellow
case 6: setPixelColor(i, 255, 25, 125); break; // Hot Pink
case 7: setPixelColor(i, 255, 150, 50); break; // Warm White
case 8: setPixelColor(i, 255, 65, 255); break; // Purple
case 9: setPixelColor(i, 50, 200, 255); break; // Light Blue
case 10: rainbow(20); break; // Rainbow
}
}
}
lastState[i] = newState;
}
} //END of loop()
// s e t P i x e l C o l o r ( )
//================================================^================================================
//
void setPixelColor(int pixelNumber, int r, int g, int b)
{
strip.setPixelColor(pixelNumber, strip.Color(r, g, b));
strip.show();
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}
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);
}
//END of setPixelColor()
indicates "number of pixels in the string" will always be "one" (for all five)
indicates "which pixel index in the string" which will always be the "zeroth" pixel.
The "strip" needs the "array" brackets and a "zero". Without the bracketed index ("0"), it (all the "objects") is talking to all the arrays, which are on all the pins.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define NUM_BUTTONS 5
#define PIXEL_COUNT 5
//Button Pins
const uint8_t buttonPins[NUM_BUTTONS] = {2, 3, 4, 5, 6};
const byte PIXEL_PIN = 8;
const byte heartbeatLED = 13;
//Create ONE NeoPixel Strip
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
boolean lastState[NUM_BUTTONS];
int mode[NUM_BUTTONS];
unsigned long heartbeatTime;
unsigned long heartbeatInterval = 500ul;
// s e t u p ( )
//================================================^================================================
//
void setup()
{
pinMode(heartbeatLED, OUTPUT);
for (int i = 0; i < NUM_BUTTONS; i++)
{
pinMode(buttonPins[i], INPUT_PULLUP);
lastState[i] = HIGH;
mode[i] = 0;
}
strip.begin();
strip.clear();
strip.show();
strip.setBrightness(50);
} //END of setup()
// l o o p ( )
//================================================^================================================
//
void loop()
{
//======================================================================== T I M E R heartbeatLED
//Is it time to toggle the heartbeat LED ?
if (millis() - heartbeatTime >= heartbeatInterval)
{
// Restart this TIMER.
heartbeatTime = millis();
// This gives us an indication if our sketch is non-blocking.
// Toggle the heartbeat LED.
digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
}
//======================================================================== Handle Pixel Strip
for (int i = 0; i < NUM_BUTTONS; i++)
{
boolean newState = digitalRead(buttonPins[i]);
if ((newState == LOW) && (lastState[i] == HIGH))
{
//Debounce
delay(20);
newState = digitalRead(buttonPins[i]);
if (newState == LOW)
{
if (++mode[i] > 10) mode[i] = 0;
switch (mode[i])
{
case 0: setPixelColor(i, 0, 0, 0); break; // Off
case 1: setPixelColor(i, 255, 0, 0); break; // Red
case 2: setPixelColor(i, 0, 255, 0); break; // Green
case 3: setPixelColor(i, 0, 0, 255); break; // Blue
case 4: setPixelColor(i, 255, 255, 255); break; // White
case 5: setPixelColor(i, 255, 255, 0); break; // Yellow
case 6: setPixelColor(i, 255, 25, 125); break; // Hot Pink
case 7: setPixelColor(i, 255, 150, 50); break; // Warm White
case 8: setPixelColor(i, 255, 65, 255); break; // Purple
case 9: setPixelColor(i, 50, 200, 255); break; // Light Blue
case 10: rainbow(i, 20); break; // Rainbow
}
}
}
lastState[i] = newState;
}
} //END of loop()
// s e t P i x e l C o l o r ( )
//================================================^================================================
//
void setPixelColor(int pixelNumber, int r, int g, int b)
{
strip.setPixelColor(pixelNumber, strip.Color(r, g, b));
strip.show();
} //END of setPixelColor()
// r a i n b o w ( )
//================================================^================================================
//
void rainbow(byte i, uint8_t wait)
{
for (uint16_t j = 0; j < 256; j++)
{
strip.setPixelColor(i, Wheel(j));
strip.show(); // update strip each step
delay(wait);
}
} //END of rainbow()
// W h e e l ( )
//================================================^================================================
//
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);
} //END of Wheel()
// E N D
//================================================^================================================