0

I am working on a led strip project and was looking for ways to smooth transition from color to another. Problem is my current method is not so good.

#include <Adafruit_NeoPixel.h> #define LED_PIN 25 #define LED_COUNT 60 #define BRIGHTNESS 50 Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800); bool isFading = false; unsigned long startTime; uint32_t fadeDuration = 1000; //fade for 3seconds uint32_t startingColor = 0x00ffff00; // W = 0x00 R=0xFF G=0xFF B=0x00 yellow uint32_t targetColor = 0x008f00ff; // W = 0x00 R=0x8F G=0x00 B=0xff violet void setup() { pinMode(25, OUTPUT); digitalWrite(25, LOW); Serial.begin(9600); while (!Serial); Serial.println("Starting"); strip.begin(); strip.show(); strip.setBrightness(BRIGHTNESS); for (int i = 0; i < strip.numPixels(); i++) strip.setPixelColor(i, startingColor); strip.show(); delay(5000); // wait 5 seconds before fading isFading = true; startTime = millis(); } void loop() { if (isFading) { //Fade from yellow to violet in 3 seconds for (int i = 0; i < strip.numPixels(); i++) strip.setPixelColor(i, getFadeColor(startingColor, targetColor, startTime, startTime + fadeDuration)); strip.show(); } if ( millis() >= startTime + fadeDuration){; // i intentionally did not include an overflow check to keep it simple Serial.println("Fade ended"); isFading = false; } } uint32_t getFadeColor(uint32_t startColor, uint32_t endColor, unsigned long timeStart, unsigned long timeEnd) { uint8_t startWhite = (startColor >> 24) & 0xff; uint8_t startRed = (startColor >> 16) & 0xff; uint8_t startGreen = (startColor >> 8 ) & 0xff; uint8_t startBlue = startColor & 0xff; uint8_t endWhite = (endColor >> 24) & 0xff; uint8_t endRed = (endColor >> 16) & 0xff; uint8_t endGreen = (endColor >> 8) & 0xff; uint8_t endBlue = endColor & 0xff; unsigned long timeNow = millis(); uint8_t mapTime = map(timeNow, timeStart, timeEnd, 0, 255); uint8_t white = map(mapTime, 0, 255, startWhite, endWhite); uint8_t red = map(mapTime, 0, 255, startRed, endRed); uint8_t green = map(mapTime, 0, 255, startGreen, endGreen); uint8_t blue = map(mapTime, 0, 255, startBlue, endBlue); Serial.print("Time: \t"); Serial.print(mapTime); Serial.print('\t'); Serial.print("Color now: \t"); Serial.println(strip.Color( red, green, blue, white),HEX); return strip.Color( red, green, blue, white); } 

The problem im having with this code is visually it would seem that it goes from

Yellow -> White -> violet

and it does not look like a proper transition. I have tried with other colors, and it always seems to pass throught the white color

Are there color theories i can apply for the transition? if you can show me an example sketches on how to do the transition that would also be great.

3
  • That happens if you directly fade between complementary colors. After half of the duration the components will be somewhere half brightness. So that looks white. How do you want it to fade between them? Commented Nov 14, 2021 at 19:47
  • Im not really sure how i want it, i guess something that will go through the color wheel until the destination color. Are there other options? Commented Nov 14, 2021 at 20:26
  • @DrakeJest: If you want to go around (rather than across) the color wheel, you should interpolate in the HSV, rather than the RGB color space. Commented Nov 14, 2021 at 20:42

1 Answer 1

2

something that will go through the color wheel until the destination color

For that the FastLED library has the function ColorHSV(), which can be used to define colors using the HSV color space. It stands for Hue, Saturation and Value (or brightness). Hue is the value representing the position in the color wheel, so that is what you want to change.

Instead of

strip.Color( red, green, blue, white); 

use

strip.ColorHSV( hue, saturation, brightness ); 

and change hue over time with the algorithm, that you already programmed. When saturation and brightness stay the same the LEDs will cycle through the color wheel.

Note: The library provides the way from HSV to RGB color (with the above function), but it does not provide a way back. For getting back HSV from an RGB color you would need to write your own conversion function and I don't know how to do that. Though at the current state you don't need it.

5
  • I have looked into the colorHSV() function, so it returns the 32bit WRGB to be used in setPixelColor(). What i have is the starting RGB and the endpoint RGB, and i need to convert them to starting hue and enpoint hue. You mentioned that i do not need a function to convert RGB to HSV, so how do i get my start and end hue values? Commented Nov 15, 2021 at 12:39
  • My point was that the library doesn't have a function for going that way. I would suggest that you use an online color picker too to determine the HSV values and then just using them in the code (so that you don't use RGB values of your colors in your code). A short google search gave me this one. Input your RGB values, press Enter and then copy the HSV values. Commented Nov 15, 2021 at 13:33
  • By the way: When you look at the image of the HSV representation cylinder in the HSL and HSV wikipedia article you can see why you got white with your code. You moved at a straight line from one side of the cylinder to the other, passing the white in the middle in the process. Thats a good visual representation to help you understand the color space Commented Nov 15, 2021 at 13:40
  • Unfortunately my color source are generated by the code and will always output a RGB value. So i have two options rewrite a portion of my code and convert everything to HSV or use formulas like the one discussed here. i will have to think about it which is more compatible of what other things i might add to this project :) Commented Nov 15, 2021 at 14:53
  • there's a lot of rgb to hsl stand-alone snippets floating around. Commented Nov 16, 2021 at 18:39

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.