Как сгладить переход на другой цвет NEOPIXELS

Я работаю над проектом светодиодной ленты и искал способы плавного перехода от одного цвета к другому. Проблема в том, что мой нынешний метод не так хорош.

#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;          //затухание в течение 3 секунд
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); // подождите 5 секунд перед исчезновением



  isFading = true;
  startTime = millis();
}



void loop() {


  if (isFading) { //Выцветает от желтого до фиолетового за 3 секунды
    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);

}

Проблема, с которой я сталкиваюсь с этим кодом, заключается в том, что визуально может показаться, что он идет от

Желтый -> Белый ->> фиолетовый>>

и это не похоже на правильный переход. Я пробовал использовать другие цвета, и мне всегда кажется, что они проходят через белый цвет

Существуют ли цветовые теории, которые я могу применить для перехода? если вы можете показать мне примерные скетчи о том, как выполнить переход, это также было бы здорово.

, 👍0

Обсуждение

Это происходит, если вы непосредственно переходите между дополнительными цветами. По истечении половины продолжительности компоненты будут иметь примерно половину яркости. Так что это выглядит белым. Как ты хочешь, чтобы это исчезло между ними?, @chrisl

Я не совсем уверен, как я этого хочу, я думаю, что-то, что будет проходить через цветовое колесо до нужного цвета. Есть ли другие варианты?, @DrakeJest

@DrakeJest: Если вы хотите обойти (а не пересечь) цветовое колесо, вам следует интерполировать в HSV, а не в цветовом пространстве RGB., @Edgar Bonet


1 ответ


2

что-то, что будет проходить через цветовое колесо до нужного цвета

Для этого в библиотеке FastLED есть функция ColorHSV(), которая может использоваться для определения цветов с использованием цветового пространства HSV. Это означает Hue, Saturation и Value (или яркость). Оттенок-это значение, представляющее положение в цветовом круге, так что это то, что вы хотите изменить.

Вместо

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

использовать

strip.ColorHSV( hue, saturation, brightness );

и меняйте оттенок с течением времени с помощью алгоритма, который вы уже запрограммировали. Когда насыщенность и яркость останутся прежними, светодиоды будут перемещаться по цветовому колесу.

Примечание: Библиотека обеспечивает переход от HSV к цвету RGB (с помощью вышеуказанной функции), но не обеспечивает обратный путь. Для возврата HSV из цвета RGB вам нужно будет написать свою собственную функцию преобразования, и я не знаю, как это сделать. Хотя в нынешнем состоянии вам это не нужно.

,

Я изучил функцию colorHSV (), поэтому она возвращает 32-битный WRGB для использования в setPixelColor(). У меня есть начальный RGB и конечный RGB, и мне нужно преобразовать их в начальный оттенок и оттенок точки. Вы упомянули, что мне не нужна функция для преобразования RGB в HSV, так как же мне получить начальные и конечные значения оттенка?, @DrakeJest

Я имел в виду, что в библиотеке нет функции для этого. Я бы посоветовал вам также использовать онлайн-палитру цветов для определения значений HSV, а затем просто использовать их в коде (чтобы вы не использовали значения RGB ваших цветов в своем коде). Короткий поиск в Google дал мне [этот](https://www.developmenttools.com/color-picker/). Введите значения RGB, нажмите Enter, а затем скопируйте значения HSV., @chrisl

Кстати: Когда вы смотрите на изображение цилиндра представления ВПГ в [статье википедии о ВПГ и ВПГ](https://en.wikipedia.org/wiki/HSL_and_HSV) вы можете понять, почему у вас белый цвет с вашим кодом. Вы двигались по прямой линии от одной стороны цилиндра к другой, проходя при этом белый цвет посередине. Это хорошее визуальное представление, которое поможет вам понять цветовое пространство, @chrisl

К сожалению, мой источник цвета генерируется кодом и всегда будет выводить значение RGB. Поэтому у меня есть два варианта: переписать часть своего кода и преобразовать все в HSV или использовать формулы, подобные той, которая [обсуждалась здесь](https://math.stackexchange.com/questions/556341/rgb-to-hsv-color-conversion-algorithm). мне придется подумать об этом, что более совместимо с тем, что еще я мог бы добавить в этот проект :), @DrakeJest

существует множество автономных фрагментов rgb и hsl, плавающих вокруг., @dandavis