HEX values for Neopixel strip

I'm having a little trouble understanding HEX values (because of my nativity with HEX) for colors and working with an Adafruit Neopixel Stick 8. My processor is an ESP32. I'm just testing the first Neopixel on the stick.

I've written a little sketch to check the color order of the Neopixels which I seem to have correct with NEO_GRB.

The first part of the loop correctly lights the Neopixel in order of R,G,B per the for loop to advance the Hex value.

The Second part of the Main loop uses predefined HEX color values to sequence thru R,G, B and DOES NOT work correctly but rather sequences: G,B,B. Here is the Serial printout:

FF0000
FF00
FF

F800
7E0
1F

What am I missing, or need to understand about HEX color value? My understanding is that, for instance, RED is FF0000 not F800?

Thanks for your patience in advance.

Mark

// A basic sketch to test color order for NeoPixels

// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
//   connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
//   a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)

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

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN DAC2

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 1

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, 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)


// setup() function -- runs once at startup --------------------------------

void setup() {
  Serial.begin(115200);
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  strip.begin();             // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();              // Turn OFF all pixels ASAP
  strip.setBrightness(150);  // Set BRIGHTNESS to about 1/5 (max = 255)
}

static const uint16_t ORANGE = 0xFD20;
static const uint16_t PINK = 0xF81F;
static const uint16_t RED = 0xF800;
static const uint16_t GREEN = 0x07E0;
static const uint16_t BLUE = 0x001F;
static const uint16_t CYAN = 0x07FF;
static const uint16_t MAGENTA = 0xF81F;
static const uint16_t YELLOW = 0xFFE0;
static const uint16_t BLACK = 0x0000;

// loop() function -- runs repeatedly as long as board is on ---------------

void loop() {


  for (uint32_t color = 0xFF0000; color > 0; color >>= 8) {  // test correct color order
    strip.setPixelColor(0, color);
    Serial.println(color, HEX);
    strip.show();
    delay(1000);
  }

  strip.clear();
  strip.show();
  delay(1000);
  Serial.println();

  strip.setPixelColor(0, RED);
  strip.show();
  Serial.println(RED, HEX);
  delay(1000);
  strip.clear();
  strip.show();
  delay(1000);
  strip.setPixelColor(0, GREEN);
  strip.show();
  Serial.println(GREEN, HEX);
  delay(1000);
  strip.clear();
  strip.show();
  delay(1000);
  strip.setPixelColor(0, BLUE);
  strip.show();
  Serial.println(BLUE, HEX);
  delay(1000);
  strip.clear();
  strip.show();

  Serial.println();

  delay(2000);
}

Correct, they should all be 6 hex-digits long for use with the NeoPixel library.

Where did you get F800 from? It could be a value for red from the "565" colour map, where red and blue are represented by 5 bits and green by 6 bits.

You can convert from the 565 colourspace to the normal NeoPixel colourspace, which is 888, with a macro (untested):

#define C565(c) (((c) & 0xF800ul) << 8 | ((c) & 0x07E0ul) << 5 | ((c) & 0x001Ful) << 3)

@PaulRB It got the stand HEX values for my colors from this post:

And BTW, yes, I have a 300 ohm resistor on my signal line of the neopixels and a 1000ufd cap on the VCC rails.

I have tried:

static const uint16_t RED = 0xFF0000;
static const uint16_t GREEN = 0x00FF00;
static const uint16_t BLUE = 0x0000FF;

But that does not work?

obviously, my real intent for this is to get predefined colors that I can call on to set my Neopixel color...

That code converts the 565 colour values into the 888 values that NeoPixel needs, but in a different way to my suggested macro.

Good, you should have those components. Not having them would cause problems, but not the problems you describe.

No, it would not. The hex values are 24 bits long. Each hex digit translates to 4 binary digits.

But uint16_t can hold only 16 bits, so some bits are lost. Try uint32_t instead.

Also, the static keyword is unnecessary, because these are constants.

Did you try my suggested macro? Let me know if you need help with that.

Yes, suspecting that that HEX was greater than 16bit I had tried that earlier, but it did not work, but it does now, thanks. I'll try your macro next so I can keep my list of predefined colors and see if it works.

thanks

Can you walk me thru what your macro is accomplishing and how to incorporate it with my current predefined colors?

#define C565(c) (((c) & 0xF800ul) << 8 ((c) & 0x07E0ul) << 5 | ((c) & 0x001Ful) << 3)

thanks

Mark

The bitwise and operator & is used three times to select only the relevant bits for each of the primary colours R, G and B.

The shift left operator << is used three times to move the selected bits to where they want to be when in a 24 bit colour.

The bitwise or operator | is used to combine the three selected and shifted colour components.

So the 565 bits

RrrrrGgggggBbbbb

end up

Rrrrr000Gggggg00Bbbbb000

Or if you put a space between the bytes

Rrrrr000 Gggggg00 Bbbbb000

#define C565(c) (((c) & 0xF800ul) << 8 | ((c) & 0x07E0ul) << 5 | ((c) & 0x001Ful) << 3)
 (c & 0xF800ul) << 8     |     (c & 0x07E0ul) << 5     |     (c & 0x001Ful) << 3)

The 'c' is in extra parentheses to make it work in the macro reliably. But the big expression is just moving the 16 bits of the 565 colour into the right places for a 32 bit RGB colour.

HTH

a7

Thank you for the explanation.

I've never defined a macro like that and I'm unclear as to what is the resultant C565(c) is?

Can you explain how that can be applied to my current list of HEX color definitions - i.e. format?

In other words, how do I apply the maco definition to my final color definitions (RED, Green, Blue, Cyan, Magenta, etc.)

You could fix all your constants in place

static const uint16_t ORANGE = 0xFD20;

like

const uint32_t ORANGE = c565(0xFD20);

and then use those names

  strip.setPixelColor(42, ORANGE);

or however.

c565() takes a 16 bit 5-6-5 coded color and converts it to 24 bit format used by the neopixel library.

HTH

a7

@alto777 and @Delta_G Thank you for your responses. This does work and I better understand what the macro is doing. Thank you for sharing your knowledge on this subject and doing macros like this will come in handy for future projects.

Mark

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.