help: little hue/brightness controller for 10 neopixels

Hello!
I’m starting to learn electronics, and I’m still super noob with coding in Arduino.
(I can copy/build simple projects from other people, but I’m far from understanding it enough to write my own code)
If anyone could help me with this little first project I would be super grateful. :open_mouth:

What I want is to have 10 portable Neopixels with a little controller from which I can:

  • choose between “solid color mode” or “rainbow cycle mode”
  • on “solid mode” I’d like to choose the hue with a Pot
  • on “rainbow mode” I’d like to choose the speed animation with that same Pot
    (I could give up on this speed feature if it adds too much complexity, though)
  • a second pot to choose the overall brightness (for the solid or the rainbow, whichever is on)

I've built something like the attached image (with 10 leds instead - powered from external source).
The hardware part so far seems ok. My problem is the coding.
~
I searched a lot but couldn't find anything close enough to my project that I'm capable of tweaking myself, right now :frowning:

The closest I found so far is the code below
(but this only let you choose from specific colors with the pushbutton and then change the brightness with a pot. I wish I could add the rainbow mode to the "menu" and be able to choose the hue through the pot, instead of the button)

#include <Adafruit_NeoPixel.h>
#define BUTTONPIN_G   2   
#define PIXEL_PIN    6    // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 10
int potentiometerG = A2;
int brightness;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
  bool oldState = HIGH;
  int showType = 0;

  void setup() {
  pinMode(potentiometerG, INPUT);
  pinMode(BUTTONPIN_G, INPUT_PULLUP);
  strip.begin();
  strip.show();
  // Set the strip to shite on powerup
  uint32_t startcolor = strip.Color(127 * brightness / 100, 127 * brightness / 100, 127 * brightness / 100);
     Allcolor(startcolor);
               
  strip.show(); //Show the start color
  startShow(showType);
}
void loop() {
   // Here we'll use the reading from the potentiometer to set the brightness   
   brightness = map(analogRead(potentiometerG), 0, 1023, 0, 100); 
  // Get current button state.
  bool newState = digitalRead(BUTTONPIN_G);
  // 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(BUTTONPIN_G);
    if (newState == LOW) {
      showType++;
      if (showType > 9)
        showType=0;
    strip.show(); // Display the LEDs   
    }
  }
  // Set the last button state to the old state.
  oldState = newState;
  startShow(showType);
}
 
void startShow(int i) {
 
  switch(i){
    case 0: {
    uint32_t white = strip.Color(127 * brightness / 100, 100 * brightness / 100, 10 * brightness / 100);
            Allcolor(white);
    } 
            break;
           
    case 1: { 
    uint32_t red = strip.Color(255 * brightness / 100, 0, 0);
            Allcolor(red);
    }
            break;
           
    case 2: {
    uint32_t orange = strip.Color(255 * brightness / 100, 40 * brightness / 100, 0);
            Allcolor(orange);

    }
            break;
    case 3:{
    uint32_t yellow = strip.Color(175 * brightness / 100, 100 * brightness / 100, 0);
            Allcolor(yellow);
    }
            break;
    case 4: {
    uint32_t green = strip.Color(0, 255 * brightness / 100, 0);
            Allcolor(green);
    }
            break;
    case 5: {
    uint32_t cyan = strip.Color(0, 175 * brightness / 100, 100 * brightness / 100);
            Allcolor(cyan);

    }
            break;
    case 6:{
    uint32_t blue = strip.Color(0, 0, 255 * brightness / 100);
            Allcolor(blue);
    }
            break;
           
    case 7: {
    uint32_t purple = strip.Color(80 * brightness / 100, 0, 100 * brightness / 100);
            Allcolor(purple);
    }
            break;
    case 8: {
    uint32_t violet = strip.Color(255 * brightness / 100, 0, 20 * brightness / 100);
            Allcolor(pink);
    }
            break;
    case 9:{
    uint32_t pink = strip.Color(255 * brightness / 100, 1 * brightness / 100, 10 * brightness / 100);
            Allcolor(pink);
    }
            break;

  }
}


 void Allcolor(uint32_t c) {
  for(int i = 0; i < PIXEL_COUNT; i++ ) {
    strip.setPixelColor(i, c);

  }
   strip.show();
  }

Example of rainbow animation that I'd like to include:

#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 10
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 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)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

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

// aqui

void loop() {
  rainbowCycle(20);
}

void rainbowCycle(int SpeedDelay) {
  byte *c;
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< NUM_LEDS; i++) {
      c=Wheel(((i * 256 / NUM_LEDS) + j) & 255);
      setPixel(i, *c, *(c+1), *(c+2));
    }
    showStrip();
    delay(SpeedDelay);
  }
}

byte * Wheel(byte WheelPos) {
  static byte c[3];
 
  if(WheelPos < 85) {
   c[0]=WheelPos * 3;
   c[1]=255 - WheelPos * 3;
   c[2]=0;
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   c[0]=255 - WheelPos * 3;
   c[1]=0;
   c[2]=WheelPos * 3;
  } else {
   WheelPos -= 170;
   c[0]=0;
   c[1]=WheelPos * 3;
   c[2]=255 - WheelPos * 3;
  }

  return c;
}

// aqui

void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
 #endif
}

void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

Huge thanks in advance to anyone that could help me with this! <3


You have the led strip connected to the Vin pin. That's probably not correct. But it's hard to say because we don't know how you will power the circuit when away from the PC.

My suggestions would be either:

A li-ion battery such as 18650 size or a li-po pack. These are around 3.7V and you can power the Nano and led strip directly from it. On the Nano, connect the battery to the 5V pin, not the Vin pin. Of course, you need a special charger for this type of battery. Also they can be damaged by over-discharging. Some 18650 batteries have a built-in protection circuit. For li-po packs, you can buy a small charging and protection board.

A holder for 3xAA NiMh batteries. This will have a voltage around 3.75V and you can use an ordinary battery charger. Connect the Nano and LEDs as explained above.

+1 karma for using code tags in your first post. If would be helpful if you can get into the habit of using Tools->Auto Format before you post your code. Auto Format does not change how the code works at all, but makes it much more readable and easier to spot mistakes.

Of your 2 sketches, a guess the first one will make a better starting point. It has code to read and debounce the button. You can modify that and move parts of the other sketch into it. If also has code to control the switching between modes. It currently has 10 modes for 10 different colours. You will only need 2 modes.

The second sketch is not so good. It is written in a style we call "blocking code" because it uses the delay() command inside a loop. This makes it respond to button pressed and pot adjustments very slowly or not at all. So need to adapt parts copied over the new sketch carefully to avoid this problem.