Улучшенное циклическое переключение цветов RGB.

Я пытался найти способ использовать 16 миллионов цветов RGB для этой светодиодной ленты. Я думал об использовании LEDS.setBrightness();, но мои попытки не увенчались успехом. Я прочитал документацию по выцветанию, но не смог записать это в свой Arduino Leonardo. Вот мой код ниже, который циклически проходит через начальную радугу 0-255. Мне было интересно, как получить больше 0-255, если не все цвета.

#include <FastLED.h>

#define LED_COUNT 60
#define LED_OUT       13
#define BUTTON_IN     10
#define ANALOG_INPUT  A9
#define EXTRA_PIN_A    7
#define EXTRA_PIN_B   11

struct CRGB leds[LED_COUNT];
int wait_time = 5;

void setup() {
  Serial.begin(57600);
  LEDS.addLeds<WS2812B, LED_OUT, GRB>(leds, LED_COUNT);
  LEDS.show();
}

void loop() {
  //начнем с красного
  for(int colorStep=0; colorStep <= 255; colorStep++) {
    int r = 255;
    int g = 0;
    int b = colorStep;
    // Теперь прокручиваем каждый из светодиодов и устанавливаем для каждого текущий цвет
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Отображение цветов, которые мы только что установили, на фактических светодиодах
    delay(wait_time);
    LEDS.show();
  }

  //в синий цвет
  for(int colorStep=255; colorStep >= 0; colorStep--) {
    int r = colorStep;
    int g = 0;
    int b = 255;
    // Теперь прокручиваем каждый из светодиодов и устанавливаем для каждого текущий цвет
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Отображение цветов, которые мы только что установили, на фактических светодиодах
    delay(wait_time);
    LEDS.show();
  }
  //начнем с синего
  for(int colorStep=0; colorStep <= 255; colorStep++) {
    int r = 0;
    int g = colorStep;
    int b = 255;
    // Теперь прокручиваем каждый из светодиодов и устанавливаем для каждого текущий цвет
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Отображение цветов, которые мы только что установили, на фактических светодиодах
    delay(wait_time);
    LEDS.show();
  }
  //в зеленый
  for(int colorStep=255; colorStep >= 0; colorStep--) {
    int r = 0;
    int g = 255;
    int b = colorStep;
    // Теперь прокручиваем каждый из светодиодов и устанавливаем для каждого текущий цвет
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Отображение цветов, которые мы только что установили, на фактических светодиодах
    delay(wait_time);
    LEDS.show();
  }
  //начнем с зеленого
  for(int colorStep=0; colorStep <= 255; colorStep++) {
    int r = colorStep;
    int g = 255;
    int b = 0;
    // Теперь прокручиваем каждый из светодиодов и устанавливаем для каждого текущий цвет
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Отображение цветов, которые мы только что установили, на фактических светодиодах
    delay(wait_time);
    LEDS.show();
  }
  //в желтый
  for(int colorStep=255; colorStep >= 0; colorStep--) {
    int r = 255;
    int g = colorStep;
    int b = 0;
    // Теперь прокручиваем каждый из светодиодов и устанавливаем для каждого текущий цвет
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Отображение цветов, которые мы только что установили, на фактических светодиодах
    delay(wait_time);
    LEDS.show();
  }
} // конец основного цикла

, 👍2

Обсуждение

но уровни RGB 0-255 _являются_ всеми цветами, что вы пытаетесь сделать?, @dandavis

это правильно, но если вы будете следовать моим циклам, вы увидите, что я делаю только комбинации 0 < 255 и 0 > 255 для rgb. IE 0, 0, 255 // синий или 255, 0, 0 // красный, поэтому я сказал начальную радугу. нет комбинаций скажем 128, 64, 250., @Oddacon

А, понятно; затем просто вставьте свои петли..., @dandavis

пробовал это как с ответом @ 6v6gt. к сожалению, он не переключает светодиоды должным образом. Кажется, существует проблема итерации с первым вложенным циклом (а не с предоставленным кодом), точно так же, как класс FastLED обрабатывает вложенность?, @Oddacon


7 ответов


Лучший ответ:

2

Думаю, стоит отметить, что три значения 255 для цветового пространства RGB — это всего лишь один из способов кодирования 255^3 (16 581 375) цветов. К ним относятся также все уровни яркости.

Если вы пытаетесь получить эффект радуги, возможно, вам удастся добиться большего успеха или вам будет проще использовать цветовое пространство HSL или HSV.

HSV использует оттенок, насыщенность и значение вместо RGB. FastLED оптимизировала свою реализацию HSV, чтобы использовать адресацию 0-255 для Hue (вместо 360), сохраняя скорость анимации, выполняемой на микроконтроллерах:

https://github.com/FastLED/FastLED/wiki/FastLED-HSV-Colors

,

Повторное использование fastled действительно очень хороший вариант! Вы преодолеете необходимость заново изобретать колесо и получите более эффективное колесо ;p, @Paul


0

Если вы хотите отобразить каждый из примерно 16 миллионов возможных цветов, вам придется вложить циклы for, как в этом примере:

x = 1 ;  // only for testing
for ( int redx = 0 ; redx <= 255 ; redx ++ ) {
    for ( int greenx = 0 ; greenx <= 255 ; greenx ++ ) {
        for ( int bluex = 0 ; bluex <= 255 ; bluex ++ ) {
             leds[ x ] = CRGB(redx,greenx,bluex);
             delay(wait_time); 
             LEDS.show(); 
        }
    }
}
,

Альтернативой может быть использование HSB или HSV вместо RGB, таким образом вы можете увеличивать оттенок с течением времени, чтобы получить эффект радуги., @Paul


0

Вы должны подумать о том, чтобы сделать его неблокирующим :)

loop(){
   //if(millis() > previous+100){//раскомментируйте эту часть, чтобы эффект радуги выполнялся каждые 100 мс
   rainbowEffect();
   //предыдущий = millis();
   //}

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

unsigned char r,g,b;
void rainbowEffect(){
   if(r>254){
      r=0;
      g++;
   }
   if(g>254){
      g=0;
      b++;
   }
   if(b>254){
      b=0;
   }
   r++;
   ledStrip.set(r,g,b);
}
,

1

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

// Циклический цикл одного RGB-светодиода с использованием техники синусоидального затухания
// Для светодиода с общим катодом

const uint8_t lights[360]={
  0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 17, 18, 20, 22, 24, 26, 28, 30, 32, 35, 37, 39,
 42, 44, 47, 49, 52, 55, 58, 60, 63, 66, 69, 72, 75, 78, 81, 85, 88, 91, 94, 97, 101, 104, 107, 111, 114, 117, 121, 124, 127, 131, 134, 137,
141, 144, 147, 150, 154, 157, 160, 163, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 202, 205, 208, 210, 213, 215, 217, 220, 222, 224, 226, 229,
231, 232, 234, 236, 238, 239, 241, 242, 244, 245, 246, 248, 249, 250, 251, 251, 252, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253,
252, 251, 251, 250, 249, 248, 246, 245, 244, 242, 241, 239, 238, 236, 234, 232, 231, 229, 226, 224, 222, 220, 217, 215, 213, 210, 208, 205, 202, 200, 197, 194,
191, 188, 185, 182, 179, 176, 173, 170, 167, 163, 160, 157, 154, 150, 147, 144, 141, 137, 134, 131, 127, 124, 121, 117, 114, 111, 107, 104, 101, 97, 94, 91,
 88, 85, 81, 78, 75, 72, 69, 66, 63, 60, 58, 55, 52, 49, 47, 44, 42, 39, 37, 35, 32, 30, 28, 26, 24, 22, 20, 18, 17, 15, 13, 12,
 11, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

const byte redpin = 3;  
const byte greenpin = 5;  
const byte bluepin = 6;  
int loopdelay = 5000; // РС
int displaylength = 50; // РС

boolean showiterations = false;  

//_______________________________
void setup() {  
      Serial.begin(9600);  
}

void loop() {  
for (int k=0; k<360; k++)  
{  
    if (showiterations) {  
    Serial.print(k);  
    Serial.print(F(","));  
    }
analogWrite(redpin, lights[(k+120)%360]);  
analogWrite(greenpin, lights[k]);  
analogWrite(bluepin, lights[(k+240)%360]);  
delay(displaylength);  
}
if (showiterations) {  
Serial.println("  ");  
}
delay(loopdelay);  
}

Этот набросок взят из публикации Instructables под названием "Как создать правильную радугу и случайные цвета с помощью цветовой модели RGB", http://www.instructables.com/id/How-to-Make-Proper-Rainbow-and-Random-Colors-With-/ Кроме того, в нем содержится информация и обоснование различных методов чередования цветов.


Если вы пытаетесь расположить цвета вдоль полосы, создавая эффект радуги, у меня есть еще один скетч [от Adafruit, я полагаю], который сделает это. Я эффективно использовал его с различными конфигурациями колец Neopixel. Скетч демонстрирует ряд различных техник. В настоящее время я закомментировал вызовы всех, кроме TheaterChaseRainbow, но вы можете изучить их все.

#include <Adafruit_NeoPixel.h>
// следующее atatement должно быть обернуто ifdef для __AVR__, но это средство портит его.
// Как бы то ни было, форматирование скетча не совсем правильное, и у меня нет для этого решения.
  #include <avr/power.h>

const  byte PIN = 7;

// Параметр 1 = количество пикселей в полосе
// Параметр 2 = номер вывода Arduino (большинство допустимо)
// Параметр 3 = флаги типа пикселя, суммируйте по мере необходимости:
// NEO_KHZ800 Битовый поток 800 кГц (большинство продуктов NeoPixel со светодиодами WS2812)
// NEO_KHZ400 400 кГц (классические 'v1' (не v2) пиксели FLORA, драйверы WS2811)
// Пиксели NEO_GRB подключены к битовому потоку GRB (большинство продуктов NeoPixel)
// Пиксели NEO_RGB подключаются к битовому потоку RGB (пиксели v1 FLORA, а не v2)
// Пиксели NEO_RGBW подключаются к битовому потоку RGBW (продукты NeoPixel RGBW)
// Полоса Adafruit_NeoPixel = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800)`
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, 6, NEO_GRB + NEO_KHZ800);

// ВАЖНО: чтобы снизить риск выгорания NeoPixel, добавьте конденсатор 1000 мкФ
// провода питания пикселя, добавить резистор 300 - 500 Ом на ввод данных первого пикселя
// и минимизировать расстояние между Arduino и первым пикселем. Избегайте подключения
// на действующей цепи... если необходимо, сначала подключите GND.

void setup() {
  // Это для Trinket 5V 16MHz, вы можете удалить эти три строки, если вы не используете Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // Конец специального кода брелока


  strip.begin();
   colorWipe(strip.Color(0, 0, 0), 50); // пустой
  strip.show(); // Инициализируем все пиксели выключенными
}

void loop() {
  // Несколько примеров процедур, показывающих, как отображать в пикселях:
// colorWipe(strip.Color(255, 0, 0), 50); // Красный
// colorWipe(strip.Color(0, 255, 0), 50); // Зеленый
// colorWipe(strip.Color(0, 0, 255), 50); // Синий
//colorWipe(strip.Color(0, 0, 0, 255), 50); // Белый RGBW
  // Отправляем погоню за пикселями кинотеатра в...
// TheaterChase(strip.Color(127, 127, 127), 50); // Белый
// TheaterChase(strip.Color(127, 0, 0), 50); // Красный
// TheaterChase(strip.Color(0, 0, 127), 50); // Синий

// радуга(20);
// delay(50000);
// colorWipe(strip.Color(0, 0, 0), 50); // пустой
// радужный цикл(10);
// delay(5000);
// colorWipe(strip.Color(0, 0, 0), 50); // пустой
// delay(5000);
  theaterChaseRainbow(50);
// delay(5000);
// colorWipe(strip.Color(0, 0, 0), 50); // пустой
// delay(5000);
}

// Заливаем точки одну за другой цветом
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Немного отличается, это делает радугу равномерно распределенной по всему
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 циклов всех цветов на колесе
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));     
    }
    strip.show();
    delay(wait);
  }
}

// Ползающие огни в театральном стиле.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  // делаем 10 циклов погони
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //включаем каждый третий пиксель
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //выключаем каждый третий пиксель
      }
    }
  }
}

// Ползающие огни в театральном стиле с эффектом радуги
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // перебираем все 256 цветов в колесе
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //включаем каждый третий пиксель
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //выключаем каждый третий пиксель
      }
    }
  }
}

// Введите значение от 0 до 255, чтобы получить значение цвета.
// Цвета — это переход r — g — b — обратно к r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
,

Хотя ваш ответ на 100% правильный, он также может оказаться на 100% бесполезным. если эта ссылка перемещена, изменена, объединена с другой или основным сайтом просто исчезает... **:(** Поэтому, пожалуйста, [отредактируйте] свой ответ и скопируйте соответствующие шаги из ссылки в ваш ответ, тем самым гарантируя ваш ответ на 100% жизни этого сайта! **;)** Вы всегда можете оставьте ссылку внизу вашего ответа в качестве источника для вашего материал..., @Avamander

@ Avamander, предложение принято, пожалуйста, переоцените., @KC Tucker


0

Я думаю, что @Mazaryk был прав, HSV — это то, что нужно для этого. Более 16 миллионов цветов RGB включают в себя яркость, и некоторые из них просто не будут отображаться на полосе, поэтому я нашел способ, по крайней мере, улучшить переход:

int thissat = 255;           //- ЦИКЛ ЗАДЕРЖКИ VAR
int idex = 0;                //-ИНДЕКС СВЕТОДИОДОВ
int ihue = 0;                //-оттенок (0-255)

void rainbow_fade() {
    ihue++;
    if (ihue > 255) {ihue = 0;}
    for(int idex = 0 ; idex < LED_COUNT; idex++ ) {
      leds[idex] = CHSV(ihue, thissat, 255);
    }
    LEDS.show();    
    delay(wait_time);
}
,

0

Вы можете воспользоваться тем, что цвет RGB может быть представлен в виде длинного числа без знака. И использовать счетчик. Но имейте терпение, перебирая 16 миллионов цветов с 1 мс на итерации, это занимает некоторое время :-). (около 4-5 часов: 16581375/(1000[мс] * 60[м] * 60[ч]) = 4,6 )

void loopThrougAllColors(){
  // Хитрость здесь заключается в использовании длинного значения без знака в качестве представления цвета.
  // Каждый байт представляет цвет (кроме первого)
  // нет, RGB
  // 0x00 00 00 00
  // Примечание: static означает, что это глобальная переменная, но она видна только в этой функции.
  static unsigned long ledColor = 0;        
  static int ledIndex = 0;

  ledColor++;
  ledColor &= 0x00FFFFFF; /* Overflow preventing (instead of if sentence checking the boundaries). */           

  leds[0] = ledColor;

  FastLED.show();
  FastLED.delay(1);
  // задержка (10);
} 
,

1

Можно создать плавный переход/эффект скользящей радуги, используя справочную таблицу синусоиды, а затем сдвинув фазу зеленого и синего на 120 и 240 градусов.

#define RED 9
#define GREEN 10
#define BLUE 11

uint8_t sins[360] = {
  127,129,131,134,136,138,140,143,145,147,149,151,154,156,158,160,162,164,166,169,171,173,175,177,179,181,183,185,187,189,191,193,195,196,198,200,
  202,204,205,207,209,211,212,214,216,217,219,220,222,223,225,226,227,229,230,231,233,234,235,236,237,239,240,241,242,243,243,244,245,246,247,248,
  248,249,250,250,251,251,252,252,253,253,253,254,254,254,254,254,254,254,255,254,254,254,254,254,254,254,253,253,253,252,252,251,251,250,250,249,
  248,248,247,246,245,244,243,243,242,241,240,239,237,236,235,234,233,231,230,229,227,226,225,223,222,220,219,217,216,214,212,211,209,207,205,204,
  202,200,198,196,195,193,191,189,187,185,183,181,179,177,175,173,171,169,166,164,162,160,158,156,154,151,149,147,145,143,140,138,136,134,131,129,
  127,125,123,120,118,116,114,111,109,107,105,103,100,98,96,94,92,90,88,85,83,81,79,77,75,73,71,69,67,65,63,61,59,58,56,54,
  52,50,49,47,45,43,42,40,38,37,35,34,32,31,29,28,27,25,24,23,21,20,19,18,17,15,14,13,12,11,11,10,9,8,7,6,
  6,5,4,4,3,3,2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,3,3,4,4,5,
  6,6,7,8,9,10,11,11,12,13,14,15,17,18,19,20,21,23,24,25,27,28,29,31,32,34,35,37,38,40,42,43,45,47,49,50,
  52,54,56,58,59,61,63,65,67,69,71,73,75,77,79,81,83,85,88,90,92,94,96,98,100,103,105,107,109,111,114,116,118,120,123,125
};
  
void setup() {
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
}

void loop() {
  for (int i = 0; i < 360; ++i)
  {
    analogWrite(RED, sins[i]);
    analogWrite(GREEN, sins[(i+120)%360]);
    analogWrite(BLUE, sins[(i+240)%360]);
    delay(2);
  }
}
,