Soru:
Dijital RGB LED animasyonu
Rhys Edwards
2014-03-14 15:41:10 UTC
view on stackexchange narkive permalink

Üzerinde çalıştığım bir proje için renklerin birbirine geçmesini sağlamaya çalışıyordum.Bunu Adafruit'un örnek kodundan bazılarının gökkuşağı etkisi ile başardım, ancak renkleri seçebilmek istiyorum ( Örneğin koyu maviden açık maviye).

Renkler değişiyor ve soluyor, ancak solma tüm LED'leri kapatıyor ve yeni rengin parlaklığını artırmaya başlıyor. Renklerin solup parlaklığı artırmak yerine karışması gerekiyor.

Biri beni doğru yönü gösterebilecek mi?

  #include "LPD8806.h" #include "SPI.h" #define stripSize 64int nLEDs = 160; int dataPin = 2; int clockPin = 3; // İlk parametre, sarmaldaki LED'lerin sayısıdır. LED şeritler // metre başına 32 LED'dir, ancak şeridi uzatabilir veya kesebilirsiniz. Sonraki iki parametre // SPI verisi ve saat pinleridir: LPD8806 strip = LPD8806 (64, dataPin, clockPin); // İsteğe bağlı olarak daha hızlı yazma için donanım SPI kullanabilirsiniz, sadece // veri ve saat pin parametrelerini dışarıda bırakın. Ancak bu, kullanımı Arduino'daki çok // özel pinlerle sınırlar. "Klasik" Arduino'lar için (Uno, Duemilanove, // vb.), Data = pin 11, clock = pin 13. Arduino Mega için, data = pin 51, // clock = pin 52. 32u4 Breakout Board + ve Teensy için veri = pin B2, // saat = pin B1. Leonardo için bu YALNIZCA ICSP pinlerinde yapılabilir.//LPD8806 strip = LPD8806 (nLEDs); void setup () {// LED strip strip.begin (); // Şeridi güncelleyin, bunların hepsi 'kapalı' olacaktır strip.show ();} void loop () {//turnAllOn(strip.Color(30,30,30),4000); solmaya (0, 127, 0, 100); // kırmızı, yeşil, mavi, gecikme - tüm pikselleri tek renk soldur //turnAllOn(strip.Color(30,100,30),4000); solmaya (50, 127, 02, 100); // kırmızı, yeşil, mavi, gecikme - tüm pikselleri tek renk soldur //turnAllOn(strip.Color(100,30,100),4000); solmaya (50, 127, 50, 100); // kırmızı, yeşil, mavi, gecikme - tüm pikselleri tek renk karartır} void fade (uint32_t r, uint32_t g, uint32_t b, uint32_t bekleme) {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 (); } gecikme (bekle);} void turnAllOn (uint32_t c, uint32_t bekleme) {int i; for (i = 0; i < strip.numPixels (); i ++) {strip.setPixelColor (i, c); // tüm pikselleri açın} strip.show (); // tüm pikselleri gecikmeye yaz (bekleyin); } uint32_t Tekerlek (uint16_t WheelPos) {byte r, g, b; anahtar (WheelPos / 128) {case 0: r = 127 - WheelPos% 128; // Kırmızı aşağı g = WheelPos% 128; // Yeşer b = 0; // mavi kapalı ara; durum 1: g = 127 - WheelPos% 128; // yeşil aşağı b = WheelPos% 128; // mavi yukarı r = 0; // kırmızı kapalı mola; durum 2: b = 127 - WheelPos% 128; // mavi aşağı r = WheelPos% 128; // kırmızı yukarı g = 0; // yeşil kapalı mola; } return (strip.Color (r, g, b));}  
Bir cevap:
Peter Bloomfield
2014-03-14 16:36:48 UTC
view on stackexchange narkive permalink

Şu anda, solma işleviniz 0'dan başlıyor ve istenen renge kadar etkili bir şekilde enterpolasyon yapıyor. Renkler arasında geçiş yapmak için eskizin kullandığı önceki rengi hatırlamanız ve sıfırdan solmaya başlamanız gerekir.

Kullanacağım yaklaşım, her bileşenin ne kadar olduğunu hesaplayarak başlamaktır her adımda değişmesi gerekiyor. Örneğin, 50 adımda 100'den 200'e geçmek istiyorsanız, her adımda +2 ile değişmesi gerekir. Aynısını ters yönde (200'den 100'e) yapmak istiyorsanız, o zaman -2'ye kadar değişmesi gerekir.

Sorunlardan biri, her bileşenin muhtemelen farklı bir miktarda değişmesidir (kırmızı olabilir 0'dan 200'e gidin, ancak mavi yalnızca 50'den 70'e çıkabilir). Her zaman tamsayı kullanıyorsanız, bazı düzensiz geçişlere neden olabilir, bu nedenle bunun yerine kayan nokta kullanmanızı öneririm. Teknik olarak daha yavaştır (daha az verimli), ancak muhtemelen endişelenecek kadar değil.

Muhtemelen bunu şöyle yazardım:

  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) {// Sıfıra bölmeye karşı koruma if (numSteps == 0) numSteps = 1; // Her adımda her bir rengin ne kadar değişmesi gerektiğini hesaplayın const float stepR = (newR - oldR) / (float) numSteps, stepG = (newG - oldG) / (float) numSteps, stepB = (newB - oldB) / (float) numSteps; // Bu değerler renkleri float r = oldR, g = oldG, b = oldB; uint8_t baytR = eskiR, baytG = eskiG, baytB = eskiB; // Her soldurma adımına gidin const uint16_t numPixels = strip.numPixels (); for (uint32_t step = 0; step < numSteps; ++ step) {// Hedef renge doğru bir adım git r + = stepR; g + = adımG; b + = adımB; // Burada renkleri tamsayılara yuvarlayın, böylece byteR = (uint8_t) (r + 0.5f) altındaki döngüde tekrar tekrar yapmak zorunda kalmayız;
baytG = (uint8_t) (g + 0.5f); baytB = (uint8_t) (b + 0.5f); // (uint16_t pixel = 0; pixel < numPixels; ++ pixel) {strip.setPixelColor (pixel, byteR, byteG, byteB) için her piksele rengi uygulayın; } strip.show (); gecikme (waitPerStep); }}  

Görebileceğiniz gibi, ona eski rengi ( buradan kayboluyor) ve yeni rengi (solmakta olduğunuz to ). Yukarıda bahsettiğim gibi bu, eskizinizin daha önce hangi rengi kullandığını hatırlaması gerektiği anlamına geliyor, çünkü kütüphanenin mevcut rengi geri okumak için bir yol sağladığını düşünmüyorum.

Bazı optimizasyonları dahil ettim. daha hızlı çalışmasını sağlamak için orada. Gerekirse onu daha da optimize etmek için yapabileceğiniz daha çok şey var.

Bunu kullanmak için şöyle bir şey yaparsınız:

  // Siyahtan kırmızıya geçiş ve kısa süreliğine duraklama (0, 0, 0, 255, 0, 0, 100, 10); gecikme (500); // Kırmızıdan mora geçiş ve kısa süreliğine durma (255, 0, 0, 255, 0, 255, 100 , 10); delay (500); // Mordan yeşile geç ve kısa bir süre solmaya ara ver (255, 0, 255, 0, 255, 0, 100, 10); delay (500);  

Kendi solma işlevi işlevinize kıyasla birkaç değişiklik daha yaptım. Her şeyden önce, kademeli geçişlerin sayısını belirleyebilmeniz için yaptım. Bu oldukça faydalı olabilir çünkü daha büyük renk değişikliklerinin düzgün görünmesi için daha fazla adım gerekir.

wait parametresini de değiştirdim. Kodunuza, tuhaf bir yaklaşım gibi görünen tüm solma tamamlandıktan sonra gecikmeyi koyarsınız. Solmanın her adımı arasında küçük bir gecikmeye izin vermek daha mantıklıdır, böylece ne kadar hızlı gittiğini kontrol edebilirsiniz.

Yukarıdaki örneğimde, her fade () çağrısının sonunda 100, 10 parametrelerini görebilirsiniz. Bu, renk değişimini her adım arasında 10 ms gecikme ile 100 adıma böleceği anlamına gelir. Sonuç olarak, her solma kabaca 1 saniye sürecektir (LED şeridi gerçekten güncellemek için geçen süre sayılmaz).

Çok iyi cevapladı. Tüm kod ayrıntıları, optimizasyonlar ve açıklamalar için tebrikler. Belki küçük bir hata: İlk adım artışıyla döngünüzü başlattığınızda başlangıç ​​rengi asla görünmez. Yalnızca döngünün sonunda bir yineleme ve artış eklemelisiniz.
@jfpoilpret Teşekkürler. İlk adımı atlamak aslında kasıtlıdır. Soruya dayanarak, LED'lerin "fade ()" çağrılmadan önce zaten "eski" rengi gösterdiğini varsayıyorum. Yine de kesinlikle haklısın. Diğer durumlarda, bu ekstra adımı gerçekten isteyebilirsiniz.
Bu gerçekten harika. Ayrıntılı yazı için çok teşekkürler!


Bu Soru-Cevap, otomatik olarak İngilizce dilinden çevrilmiştir.Orijinal içerik, dağıtıldığı cc by-sa 3.0 lisansı için teşekkür ettiğimiz stackexchange'ta mevcuttur.
Loading...