Flashing a single node of a neo pixel until a color is selected

I am trying to make a master mind/code breaker game where the player has to guess a random code that is made up of four colors. My goal is that each node of the neo pixel will fade in and out until the user cycles through the available colors and then selects a color. At which point, the node will stop flashing and then the next node will start to fade in and out until the player selects the next color for the code. Right now I have been able to get the nodes to flash until a color is selected. But once the color is selected, the next node in the sequence begins to flash ,but previous node just fade completely off.
this is my current code

#include <Arduino.h>
#include <Adafruit_NeoPixel.h>


boolean flag1 = false;
boolean flag2 = false;
boolean flag3 = false;

const int LED_PIN = 12;
const int ansLedPins[4] = {7, 8, 9, 10};
const int neoBtnPins[2] = {2, 3};
const int btnSubmit = 4;
const int dspNodeArray[4] = {0,1,2,3};
const long debounceTime = 50;
const long debounceTime2 = 500;
const long interval = 1000;
const long brtInterval = 25;
unsigned long prevMillis = 0;
static uint32_t lastPressTime = 0;
uint32_t neoPixArray[8];
uint32_t rmdPixArray[4];
uint32_t usrPixArray[4];
int colorIDX = 0;
int selectIDX = 0;
int dspNodeIDX = 0;
int dspNodeInc = 0;
int btnState = 1;
int ansIndex = 0;
int brtLevel = 100;


volatile byte state = LOW;

void cycleColor();
void selectColor();
void chkColorCode();
void randomize();
uint32_t Red;
uint32_t Blue;
uint32_t Yellow;
uint32_t Green;
uint32_t Gray;
uint32_t Magenta;
uint32_t Navy;
uint32_t Brown;







#define LED_COUNT 60


Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup()
{

  Serial.begin(9600);
  strip.begin();           
  strip.show();            
  strip.setBrightness(brtLevel); 


  pinMode(btnSubmit, INPUT);
  for(int i = 0; i < 2 ; i++ )
    {
      
      pinMode(neoBtnPins[i], INPUT);

    }
  attachInterrupt(digitalPinToInterrupt(neoBtnPins[0]), cycleColor, CHANGE);
  attachInterrupt(digitalPinToInterrupt(neoBtnPins[1]), selectColor, CHANGE);
  
  for(int l = 0; l < 4; l++)
    {
      pinMode(ansLedPins[l], OUTPUT);
    }

  for(int c = 0; c < 4; c++)
    {
      digitalWrite(ansLedPins[c], HIGH);
      delay(100);
      digitalWrite(ansLedPins[c], LOW);
      delay(100);
    }

  Red = strip.Color(139, 0, 0);
  Green = strip.Color(0, 100, 0);
  Yellow = strip.Color(139, 139, 0);
  Blue = strip.Color(0, 0, 139);
  Gray = strip.Color(192, 192, 192);
  Magenta = strip.Color(255, 69, 0);
  Navy = strip.Color(25, 25, 112);
  Brown = strip.Color(139, 69, 19);

  
  neoPixArray[0] = Red;
  neoPixArray[1] = Green;
  neoPixArray[2] = Yellow;
  neoPixArray[3] = Blue;
  neoPixArray[4] = Gray;
  neoPixArray[5] = Magenta;
  neoPixArray[6] = Navy;
  neoPixArray[7] = Brown;



  for( int n = 0; n < 4; n++ )
  {
    randomize();
    uint32_t randomColor = random(0,7);
    rmdPixArray[n] = neoPixArray[randomColor];

  }
}



void asgNodeColor( int numNode, int clrIndex)
  {
    int i = numNode;
    int j = clrIndex;
    if(flag3 == false)
      {
        Serial.print("numNode ");
        Serial.print("\t");
        Serial.print(i);
        Serial.print("\t");
        Serial.print("clrIndex ");
        Serial.print("\t");
        Serial.print(j);
        Serial.println();
        flag3 = true;
      }
    strip.clear();
    usrPixArray[i] = neoPixArray[j];
    strip.setPixelColor(i,usrPixArray[j]);
    strip.show();
    dspNodeInc++;
    colorIDX = 0;

  }

void loop()
{

  /*
  strip.setPixelColor(4,rmdPixArray[0]);
  strip.setPixelColor(5,rmdPixArray[1]);
  strip.setPixelColor(6,rmdPixArray[2]);
  strip.setPixelColor(7,rmdPixArray[3]);
  strip.show();
  */
        

  unsigned long currentMillis = millis();
    if(currentMillis - prevMillis >= brtInterval)
        {
          if(colorIDX <= 7 && dspNodeInc < 4)
            {

              strip.setPixelColor(dspNodeArray[dspNodeInc], neoPixArray[colorIDX]);
              strip.show();
        

//unsigned long currentMillis = millis();
        //if(currentMillis - prevMillis >= brtInterval)
          //{
            //prevMillis = currentMillis;
              Serial.print("dspNode ");
              Serial.print("\t");
              Serial.print(dspNodeInc);
              Serial.println();
               
               
                if(brtLevel <= 100) //&& brtLevel != 0)
                  {
              
                    strip.setBrightness(brtLevel);
             
                    brtLevel--;
                
                  }
                else if( brtLevel == 50)
                  {
                    brtLevel = 75;
                    strip.setBrightness(brtLevel);
                    //brtLevel = 75;

                  }
            
            }
        else
          {
            colorIDX = 0;
          }
        }

  
    if(digitalRead(btnSubmit) == 0 && millis() - lastPressTime > debounceTime2)
      {   
        lastPressTime = millis();
        state = !state;
        chkColorCode();
          
      }
      
      
}

void cycleColor()
{
  if(digitalRead(neoBtnPins[0]) && millis() - lastPressTime > debounceTime) 
  {
    lastPressTime = millis();
    state = !state;
    colorIDX++;
  }

}

void selectColor()
{
  if(digitalRead(neoBtnPins[1]) && millis() - lastPressTime > debounceTime) 
  {
    lastPressTime = millis();
    state = !state;
    usrPixArray[dspNodeInc] = neoPixArray[colorIDX];
    dspNodeInc++;
    colorIDX = 0;
    //asgNodeColor(dspNodeInc,colorIDX);
    flag2 = false;
    flag1 = false; 
    flag3 = false; 
    
  }

}

void randomize() 
  {
    uint32_t newSeed = 0;
    for (int i=0; i < 32; i++) 
      {
      uint32_t r = analogRead(A0);
      r <<= (analogRead(A1) >> 3) & 0x03;
      r += analogRead(A2);
      newSeed <<= 1;
      if (r & 0x04)  
        {
          newSeed |= 0x1;
        }
      }
    randomSeed(newSeed);
  }

void chkColorCode()
  {
  
        
        for(int x = 0; x < 4; x++)
          {
            if(usrPixArray[x] == rmdPixArray[x])
              {
                digitalWrite(ansLedPins[x],HIGH);
                Serial.println(usrPixArray[x]);
              }
            else if(usrPixArray[x] == rmdPixArray[0])
              {
                Serial.print("Right Color, Wrong Spot");
                Serial.println();
              }
            else if(usrPixArray[x] == rmdPixArray[1])
              {
                Serial.print("Right Color, Wrong Spot");
                Serial.println();
              }
             else if(usrPixArray[x] == rmdPixArray[2])
              {
                Serial.print("Right Color, Wrong Spot");
                Serial.println();
              }
              else if(usrPixArray[x] == rmdPixArray[3])
              {
                Serial.print("Right Color, Wrong Spot");
                Serial.println();
              }  
              else if(usrPixArray[x] != rmdPixArray[x])
              {
                Serial.print("Color Not In Code");
                Serial.println();
              }           
          }      
    
     
  }


I think part of the problem is that I am using setBrightness() and it really isn't designed for what I am trying to do.

Any help would be greatly appreciated.

Can you please write a more consistant description.
You are writing about fading in and out then about flashing

what is a "node" in this case ? Some LEDs that are crossing?
or
one simple led?

write it in paragraphs

game starts
description which leds do what

user does what to choose a color?
what are the leds doing as long as the user is choosing a colors?

description which led does what when user has chosen a first color

user starts choosing the second color
description which led does what when user has chosen a first color

etc.

I can't make sense of the logic because I can't make sense, quite, of your description of how it should work.

Having the code element I am selecting be fading and flashing woukd be very annoying during the contemplative period of analysis.

But it's your trip, so.

I would first change out the interrupt driven button handling. There is zero need for interrupts, here they are a distraction.

Just do them old school by hand, or use a button library. ezButton (small e small z big Button) doesn't suck and is easy to use.

Next, yes, drop brightness. There is no need for brightness here, or if you are stuck on it, switch to FastLED which has a proper non-destructive brightness function.

You can code a fade and you will see what you are getting because it will be what you wrote.

But I've already said I would drop that UI idea.

Then you obvsly have a logic error somewhere. You have the serial monitor, so start sprinkling some printing in there so you can confirm the value of key variables and confirm that they are properly informing the flow through your code.

Because now they aren't.

a7

I have a NeoPixel Strip that has a total of 8 LEDs, but I will only be using 4 of the LED.
When the game starts, the only LED on the NeoPixel that will be active in the first LED on the NeoPixel.

The player will use a button to cycle through a selection of 8 possible colors to choose for the first part of the color code that they are trying to guess.

While the player is deciding what color to choose, the first LED on the NeoPixel strip will fade in and out. Then when the player selects the color they think is the first part of the color code, the first LED on the NeoPixel will become a solid color.

Once a color has been selected for the first LED on the NeoPixel strip. The second LED on the NeoPixel strip will activate and begin fading in and out as the player selects the color that they think is the second color in the color combination. Once the player selects the second color in the code, the second LED turns to a solid color.

Then the process repeats with the 3rd and 4th LEDs on the pixel strip.

If the first color is chosen
then you have to make sure that the first neopixel stays on with the selected color.
and that part of your code that does the fade in/fade out has to start at nepoxiel 2 with the fading.

So analyse your code in what part of your code is the fading done?

My thought behind having the LED fade in and out is to give the Player a visual cue that they still need to select a color. When I was testing a previous version of the game I kept thinking that I had a problem with no exiting the main loop once once I had selected my guess as to which four colors made up the code that I was trying to solve. AS it turned out, there wasn't a problem with the loop at that point, the problem was that I was only selecting 3 colors and not 4 colors. That is why I decided on having the LED's fade in and out to give the player a visual cue to tell the difference between when a color has be selected or if the player needed to select a color.

I have been looking at FastLED and I am still trying to make sense of the library. I am sure that I can find a solution for my problem, but I have yet to come across anything that makes sense to me.

I have been doing that as well and as far as I can tell my values of key variables are getting passed correctly.

Currently I am trying to have the fading done in the same loop where the player would select the color they thing make up the code.

unsigned long currentMillis = millis();
    if(currentMillis - prevMillis >= brtInterval)
        {
          if(colorIDX <= 7 && dspNodeInc < 4)
            {

              strip.setPixelColor(dspNodeArray[dspNodeInc], neoPixArray[colorIDX]);
              strip.show();
        

//unsigned long currentMillis = millis();
        //if(currentMillis - prevMillis >= brtInterval)
          //{
            //prevMillis = currentMillis;
              Serial.print("dspNode ");
              Serial.print("\t");
              Serial.print(dspNodeInc);
              Serial.println();
               
               
                if(brtLevel <= 100) //&& brtLevel != 0)
                  {
              
                    strip.setBrightness(brtLevel);
             
                    brtLevel--;
                
                  }
                else if( brtLevel == 50)
                  {
                    brtLevel = 75;
                    strip.setBrightness(brtLevel);
                    //brtLevel = 75;

                  }
            
            }
        else
          {
            colorIDX = 0;
          }
        }

I tried to write another function that would assign the code to the an array that is generated as the Player selects the colors and tried to use that function to keep the first led on:

void asgNodeColor( int numNode, int clrIndex)
  {
    int i = numNode;
    int j = clrIndex;
    if(flag3 == false)
      {
        Serial.print("numNode ");
        Serial.print("\t");
        Serial.print(i);
        Serial.print("\t");
        Serial.print("clrIndex ");
        Serial.print("\t");
        Serial.print(j);
        Serial.println();
        flag3 = true;
      }
    strip.clear();
    usrPixArray[i] = neoPixArray[j];
    strip.setPixelColor(i,usrPixArray[j]);
    strip.show();
    dspNodeInc++;
    colorIDX = 0;

  }

I ultimate commented out the call to that function because it wasn't keeping the first led one. It doesn't seem to matter where I put the code to keep the first LED on because no mater where I put the code to keep the LED on because the first LED still turns off.

I have no clue what "asgNodeColor" means.

what does

do?

switching all LEDs to black?
Never looked into fastLED so me personal I don't know. But sounds plausible.

in general your variable names use words but to me these names are not selfexplaining.

what is the meaning of "numNode" ?
"clrIndex" some index gets cleared but what does that mean in your code?

flag1, flag2, flag3 etc.

what conditions do set flag1 to true?
what conditions do set flag2 to true?
what conditions do set flag3 to true?

You should give these flags a self-explaining name

example:

userPressedSetColorButton = true;

so reading your code does explain itself

if (userPressedSetColorButton) {
  ledIndexFadingLeds++;  // increment index-number of those leds that shall still be fading by 1
}

asgNodeColor is a function that is passed what the current LED is waiting to be assigned a color by the player. numNode is variable name for the current LED. All of the documentation and examples I have been looking at for the NeoPixel strips refer to the individual LEDs on the NeoPixel Strip as Nodes with Node 0 being the first LED on the strip. Granted all of the documentation and examples I have been looking at have been created by Adafruit, so I am not sure if this is a standard way of referring to the individual LEDs on the NeoPixel Strip.

clrIndex is a variable that is referring to the index of the array that contains all of the possible color's that the player can choose from.

strip.clear();

is a command that clears/resets the NeoPixel strip so all of the LEDs are turned off.

strip.show();

is the command that outputs whatever color is assigned to the individual LEDs of the NeoPixel strip.

So the lines

I was just using the flag variables to help me trouble shoot loops and some other parts of my code. I was using the flags to stop loops so I could see what variable changed values as I was pressing the buttons to cycle through the possible selection of color and when I press the button that would assign a color to an array that was generated from input given by the player.

as the function asgNodeColor uses

    strip.clear();

This causes all leds to be switched off.

This attempt to explain is just confusing

The function is passed? Passed to what?

passing in the context of programming is "handing over" a variable or a value to a function

so

myFunction(2);

the value 2 is passed to the function.

myFunction(myVar);

the value of variable myVar is passed to the function.

as a quick shot into the fog take out the

    strip.clear();

and test if it works then.

another way of debugging and to learn what line of code does what
is to use a self written function that
waits for a button to be pressed and only if button is pressed continue
combined with printing a specific message to the serial monitor

I think you give the answer yourself here...
You need to change the brightness of one led here, not the whole strip...
Problem is that your colours are coded as uint32_t.
I am not familiar with this neopixel library. But it would be way easier to start from colors coded as an array (or struct) of 3 uint8_t values (RGB).
Then it is pretty obvious how to reduce brightness:
simply divide each value by an increasing number.
I am pretty sure the library has some way to set a color from rgb values...

Just a comment, not a solution:

Neopixels will not give you gray and brown. Rather, not-so-bright white and dim orange.

Yeah, it was one of the first things that I noticed as I was working on the project, but this particular issue is small compared to the other parts of the code. So I figured that I would correct that issue after I got the other issues worked out.

I imagine a structure or multi(5)-dimensional array for the row, position, guess, colors right, positions right.

setBrightness() just use once in setup() so in the game, change the "brightness" by changing the color value (0 to 255).

I am sorry I missed a word in a sentence:

This is the code that is triggered when the player pushes a the button to select a color:

void selectColor()
{
  if(digitalRead(neoBtnPins[1]) && millis() - lastPressTime > debounceTime) 
  {
    lastPressTime = millis();
    state = !state;
    usrPixArray[dspNodeInc] = neoPixArray[colorIDX];
    dspNodeInc++;
    colorIDX = 0;
    //asgNodeColor(dspNodeInc,colorIDX);`
    flag2 = false;
    flag1 = false; 
    flag3 = false; 
    
  }

}

I have commented out the function because it doesn't work and but I didn't want to completely abandon the function in case I could make the function work later. But the function.

 //asgNodeColor(dspNodeInc,colorIDX);

takes two arguments the first argument:

dspNodeInc

is the current LED that the player is choosing a color for. That would the first, second, third or forth LED.

the second argument:

,colorIDX

is the color that has been selected by the player.

I know, that is why:

    if(flag3 == false)
      {
        Serial.print("numNode ");
        Serial.print("\t");
        Serial.print(i);
        Serial.print("\t");
        Serial.print("clrIndex ");
        Serial.print("\t");
        Serial.print(j);
        Serial.println();
        flag3 = true;
      }

is part of the the code of the function. That was my way of testing to see if the right variables were being passed to the function.

I was using strip.clear(); to clear the strip before updating the strip with color that the player selected for each of the four LEDs because when I am working with an LCD screen, that I have to clear the LCD screen before I can update the screen with new information. That is why 3 lines down in the function there is the strip.show(); command that should in theory update the NeoPixel strip with the colors selected by the player.

The neopixel library can do exactly what your saying but I couldn't figure how to work with the arrays.

I was having trouble figuring out how to create an array that has four elements where each element in the array was filled with another 3 element array.

I didn't think something like:

playerGeneratedArray[0] = color(255 , 120, 248)

would work, because I am comparing a randomly generated 4 element array against the 4 element array that is generated based on the input from the player.

Right now, I only have two arrays that have four elements, with the four elements being the colors. There is any array that is randomly generated when the program starts and a second array that is generated when the player selects a color for each LED.

I am not 100% sure what a multi-dimensional array is or if I have even used one. Would it be an array that contains another array?

I would go something like:

const int blue = 0;
const int cyan = 1
const int red  = 2;
//all other colours of the game will have their own number, so add here

//rgb coding of colours used
uint8_t pinColors[][3] = {
    {  0,   0, 255},
    {  0, 255, 255},
    {255,   0,   0},
   //add rgb code for other colours here
};
const int R = 0;
const int G = 1;
const int B = 2;

//color code that should be guessed:
int code[4];
for (int i=0; i<4; i++) {
    code[i] = //some random input (value from 0-5 if 6 colours are available)
}

int brightness = 127; //half brightness...
int colorNr = cyan;
somePixelColor = Color(
     brightness*pinColors[colorNr][R]/256, 
     brightness*pinColors[colorNr][G]/256, 
     brightness*pinColors[colorNr][B]/256
}

This example uses a 2D array to store the pinColors.
You could also make it a 1D array of structs (with members red, green and blue).
You could also use an enum to number the pinColors...
But I think that kind of stuff is not helping you now in your learning curve...

I was looking into multi-dimensional arrays after I read your last post and that does seem to be the way to go.

I have a couple of questions about the code you suggested.

For the 2D array, do I need to specify how many colors will be in the 2D array? Does the line

uint8_t pinColors[][3] = {
    {  0,   0, 255},
    {  0, 255, 255},
    {255,   0,   0},

need to read

uint8_t pinColors[8][3] = {
    {  0,   0, 255},
    {  0, 255, 255},
    {255,   0,   0},

since I will be using 8 colors?

Will I need to do

int colorNr = cyan;
somePixelColor = Color(
     brightness*pinColors[colorNr][R]/256, 
     brightness*pinColors[colorNr][G]/256, 
     brightness*pinColors[colorNr][B]/256
}

for each of the eight colors?

The compiler will derive the first [number here][3] based on the amount of info that you provide to initialize the array.
[8][3] is also allowed. And will give a warning if you have too many or too little sets of 3.

You need to adjust the brightness for the last entered color on your strip...and it needs to be non blocking...

// some code to vary brightness in non blocking way...

uint8_t colorsEntered[4];

colorNr = colorsEntered[numberOfColorsEntered]:

lastPixelColor = //see above