Hoạt hình kỹ thuật số RGB LED


7

Tôi đã cố gắng để làm cho màu sắc mờ dần vào nhau cho một dự án tôi đang làm. Tôi đã đạt được điều này với hiệu ứng cầu vồng mà một số từ mã ví dụ của Adafbean, tuy nhiên tôi muốn có thể chọn các màu (ví dụ: xanh đậm thành xanh nhạt).

Tôi đã thay đổi màu sắc và mờ dần, tuy nhiên độ mờ sẽ tắt tất cả các đèn LED và bắt đầu tăng độ sáng của màu mới. Tôi cần màu sắc để pha trộn hơn là mờ dần và tăng độ sáng.

Có ai có thể chỉ cho tôi đi đúng hướng?

#include "LPD8806.h"
#include "SPI.h"
#define stripSize 64

int nLEDs = 160;

int dataPin  = 2;
int clockPin = 3;

// First parameter is the number of LEDs in the strand.  The LED strips
// are 32 LEDs per meter but you can extend or cut the strip.  Next two
// parameters are SPI data and clock pins:
LPD8806 strip = LPD8806(64, dataPin, clockPin);

// You can optionally use hardware SPI for faster writes, just leave out
// the data and clock pin parameters.  But this does limit use to very
// specific pins on the Arduino.  For "classic" Arduinos (Uno, Duemilanove,
// etc.), data = pin 11, clock = pin 13.  For Arduino Mega, data = pin 51,
// clock = pin 52.  For 32u4 Breakout Board+ and Teensy, data = pin B2,
// clock = pin B1.  For Leonardo, this can ONLY be done on the ICSP pins.
//LPD8806 strip = LPD8806(nLEDs);

void setup() {
  // Start up the LED strip
  strip.begin();

  // Update the strip, to start they are all 'off'
  strip.show();
}

void loop() {
  //turnAllOn(strip.Color(30,30,30),4000);
  fade(0, 127, 0, 100); //red, green, blue, delay - fade up all pixels one color
  //turnAllOn(strip.Color(30,100,30),4000);
  fade(50, 127, 02,100); //red, green, blue, delay - fade up all pixels one color
  //turnAllOn(strip.Color(100,30,100),4000);
  fade(50, 127, 50, 100); //red, green, blue, delay - fade up all pixels one color
}

void fade(uint32_t r, uint32_t g, uint32_t b, uint32_t wait) {
  int i, j;
  for (j=0; j < 384; j++) {
    for (i=0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color((r*j)/1000,(g*j)/1000,(b*j)/1000));
    }
  strip.show();
  }
  delay(wait);
}

void turnAllOn(uint32_t c, uint32_t wait) {
  int i;  
  for (i=0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);  // turn all pixels on
  }
  strip.show();   // write all the pixels out
  delay(wait); 
}

uint32_t Wheel(uint16_t WheelPos)
{
  byte r, g, b;
  switch(WheelPos / 128)
  {
    case 0:
      r = 127 - WheelPos % 128;   //Red down
      g = WheelPos % 128;      // Green up
      b = 0;                  //blue off
      break; 
    case 1:
      g = 127 - WheelPos % 128;  //green down
      b = WheelPos % 128;      //blue up
      r = 0;                  //red off
      break; 
    case 2:
      b = 127 - WheelPos % 128;  //blue down 
      r = WheelPos % 128;      //red up
      g = 0;                  //green off
      break; 
  }
  return(strip.Color(r,g,b));
}

Câu trả lời:


6

Hiện tại, chức năng mờ dần của bạn đang bắt đầu từ 0 và nội suy hiệu quả đến màu mong muốn. Để làm mờ dần giữa các màu, bạn sẽ cần bản phác thảo để nhớ màu trước đó đã sử dụng và bắt đầu mờ dần từ đó thay vì từ 0.

Cách tiếp cận tôi sử dụng là bắt đầu bằng cách tính toán mỗi thành phần cần thay đổi bao nhiêu trên mỗi bước. Ví dụ: nếu bạn muốn làm mờ dần từ 100 đến 200 trên 50 bước, thì nó cần thay đổi +2 trên mỗi bước. Nếu bạn muốn làm tương tự ngược lại (200 đến 100) thì nó sẽ phải thay đổi bằng -2.

Một trong những vấn đề là mỗi thành phần có thể sẽ thay đổi bởi một lượng khác nhau (màu đỏ có thể tăng từ 0 đến 200, nhưng màu xanh chỉ có thể đi từ 50 đến 70). Nếu bạn đang sử dụng số nguyên mọi lúc thì điều đó có thể dẫn đến một số chuyển tiếp không đồng đều, vì vậy tôi khuyên bạn nên sử dụng dấu phẩy động thay thế. Đó là về mặt kỹ thuật chậm hơn (kém hiệu quả hơn), nhưng có lẽ không đủ để lo lắng.

Đây là cách tôi có thể viết nó:

void fade(uint8_t oldR, uint8_t oldG, uint8_t oldB, uint8_t newR, uint8_t newG, uint8_t newB, uint32_t numSteps, uint32_t waitPerStep)
{
    // Guard against division by zero
    if (numSteps == 0) numSteps = 1;

    // Calculate how how much each colour needs to change on each step
    const float
        stepR = (newR - oldR) / (float)numSteps,
        stepG = (newG - oldG) / (float)numSteps,
        stepB = (newB - oldB) / (float)numSteps;

    // These values will store our colours on the way along
    float r = oldR, g = oldG, b = oldB;
    uint8_t byteR = oldR, byteG = oldG, byteB = oldB;

    // Go through each fade step
    const uint16_t numPixels = strip.numPixels();
    for (uint32_t step = 0; step < numSteps; ++step) {
        // Move one step towards the target colour
        r += stepR;
        g += stepG;
        b += stepB;

        // Round the colours to integers here so we don't have to do it repeatedly in the loop below
        byteR = (uint8_t)(r + 0.5f);
        byteG = (uint8_t)(g + 0.5f);
        byteB = (uint8_t)(b + 0.5f);

        // Apply the colour to each pixel
        for (uint16_t pixel = 0; pixel < numPixels; ++pixel) {
            strip.setPixelColor(pixel, byteR, byteG, byteB);
        }

        strip.show();
        delay(waitPerStep);
    }
}

Như bạn thấy, bạn vượt qua nó màu cũ (mà bạn đang mờ dần từ ) và màu mới (mà bạn đang mờ dần đến ). Như tôi đã đề cập ở trên, điều này có nghĩa là bản phác thảo của bạn phải nhớ màu nào đã được sử dụng trước đó, vì tôi không nghĩ rằng thư viện cung cấp cách đọc lại màu hiện tại.

Tôi đã bao gồm một số tối ưu hóa trong đó để làm cho nó chạy nhanh hơn. Có nhiều hơn bạn có thể làm để tối ưu hóa nó hơn nữa, nếu cần thiết.

Để sử dụng cái này, bạn sẽ làm một cái gì đó như thế này:

// Fade from black to red and pause briefly
fade(0, 0, 0,  255, 0, 0,  100, 10);
delay(500);

// Fade from red to purple and pause briefly
fade(255, 0, 0,   255, 0, 255,  100, 10);
delay(500);

// Fade from purple to green and pause briefly
fade(255, 0, 255,  0, 255, 0,  100, 10);
delay(500);

Tôi đã thực hiện một vài thay đổi khác so với chức năng chức năng mờ dần của riêng bạn. Trước hết, tôi đã làm điều đó để bạn có thể đặt số bước làm mờ dần. Điều này có thể khá hữu ích vì những thay đổi màu lớn hơn sẽ cần nhiều bước hơn để trông mượt mà.

Tôi cũng đã sửa đổi waittham số. Trong mã của bạn, bạn đặt độ trễ sau khi toàn bộ mờ dần, có vẻ như là một cách tiếp cận kỳ lạ. Sẽ có ý nghĩa hơn khi cho phép một độ trễ nhỏ giữa mỗi bước mờ dần, vì vậy bạn có thể kiểm soát tốc độ của nó.

Trong ví dụ của tôi ở trên, bạn có thể thấy các 100, 10tham số ở cuối mỗi cuộc gọi đến fade(). Điều đó có nghĩa là nó sẽ chia sự thay đổi màu sắc thành 100 bước, với độ trễ 10ms giữa mỗi bước. Kết quả là mỗi lần mờ sẽ mất khoảng 1 giây (không tính thời gian thực sự cập nhật dải đèn LED).


1
Trả lời rất tốt. Kudos cho tất cả các chi tiết mã, tối ưu hóa và giải thích. Có thể một lỗi nhỏ: màu từ không bao giờ xuất hiện khi bạn bắt đầu vòng lặp của mình với bước tăng đầu tiên. Bạn nên thêm một lần lặp và tăng chỉ ở cuối vòng lặp.
jfpoilpret

@jfpoilpret Cảm ơn. Thiếu bước đầu tiên là thực sự có chủ ý. Dựa trên câu hỏi, tôi cho rằng đèn LED đã hiển thị màu 'cũ' trước khi fade()được gọi. Bạn hoàn toàn đúng. Trong các trường hợp khác, bạn thực sự có thể muốn thêm bước đó.
Peter Bloomfield

Điều này thực sự tuyệt vời. Cảm ơn rất nhiều cho các chi tiết viết lên!
Rhys Edwards
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.