Konwerter PWM -> analog -> WS281x

Miejsce dobre do dyskusji nad własnymi projektami - pochwal się wszystkim co samodzielnie stworzyłeś.
ODPOWIEDZ
Awatar użytkownika
Ertew
Użytkownik
Posty: 1418
Rejestracja: 03 lip 2005, 10:36
Lokalizacja: Leszno
Kontakt:

Konwerter PWM -> analog -> WS281x

Post autor: Ertew » 22 kwie 2017, 11:55

Obrazek
Konwerter powstał z potrzeby chwili. Po pozytywnych wrażeniach z taśmami RGB i systemem MiLight postanowiłem zaszaleć i kupiłem taśmę typu WS2811 12V. O ile sterowanie taśmą (uC + soft) nie stanowi dla mnie problemu, to niestety przejechałem się na pilocie. Poniższy projekt stanowi prowizoryczne obejście tego problemu. Oczywiście całość będzie działać z dowolnym sterownikiem taśm LED z wyjściem PWM, MiLight podaję jako przykład.

Krótki wstęp teoretyczny:
Ekosystem MiLight zawiera 3 podstawowe piloty:
1. Mono / CCT - regulacja jasności i temperatury światła białego
2. RGB / RGBW - wybór odcienia i jasności (bez nasycenia) lub jasności światła białego
3. RGB + CCT - wybór temperatury i jasności światła białego lub odcienia i jasności RGB lub możliwość miksowania biały + RGB.

Każdy pilot ma dedykowane odbiorniki (sterownik taśm LED i żarówki) jednak pewne kombinacje pomiędzy sterownikiem a pilotem są dozwolone. O ile odbiorniki RGB+CCT działają wyłącznie z pilotem 3, to eksperymenty pokazują że odbiorniki RGB i RGBW bezproblemowo działają z pilotami 2 i 3, a pilot 3 daje znacznie większe możliwości sterowania niż dedykowany pilot 2.

Ponieważ ceny obu pilotów są zbliżone, wybrałem pilot który daje większe możliwości.


Dlaczego nie użyję pilota MiLight i odbiornika 2.4GHz?
W internecie krąży kilka niezależnych projektów opisujących protokół i schemat ramki danych w systemie MiLight. Większość z nich opiera się na Arduino (AVR) i układach radiowych nRF24L01. Niestety wszystkie projekty obsługują stary standard RGBW a nikomu jeszcze nie udało się rozszyfrować nowego protokołu RGB+CCT.
Oczywiście w najbliższym czasie planuję zająć się hakowaniem tego nowego protokołu. Tymczasem stworzyłem obejście problemu w postaci tego konwertera. Urządzenie pobiera sygnał z wyjść sterownika RGB i przekazuje go dalej na taśmę RGB typu WS2811 lub WS2812.


Zasada działania:
-> Kontroler taśmy RGB posiada 3 wyjścia typu otwarty dren. Wraz z rezystorem 270Ω podciągającym do 5V tworzą 3 wyjścia zbliżone do standardu TTL.
-> Rezystor 2k7 i kondensator 22µF tworzą prosty filtr dolnoprzepustowy wygładzający sygnał.
-> Co kilkadziesiąt milisekund mikrokontroler odczytuje 3 sygnały analogowe i po niewielkiej obróbce wysyła je do układów WS281x umieszczonych na taśmie LED.
Żeby taśma 'pikselowa' odróżniała się od klasycznej RGB, w każdym kroku sygnał jest przesuwany o jeden piksel dalej a odczytane wartości trafiają na początek taśmy. W połączeniu z opóźnieniem generowanym przez obwód RC daje to dodatkowy efekt dynamiczny.

Oto schemat oraz kod programu, napisany na szybko w Arduino.
Obrazek
https://easyeda.com/editor#id=2b9bd79e9 ... cd460c2731

Kod: Zaznacz cały

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 5
#define numOfPx 100


// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(numOfPx, PIN, NEO_BRG + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.


void setup() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code
  

  //Serial.begin(115200);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}


void loop() {
  
  /*    // serial debug
  static const uint8_t analog_pins[] = {A0,A1,A2,A3,A4,A5,A6,A7};  // Setup pins for input

  Serial.println(" ");
  
  for (int i = 0; i < sizeof(analog_pins); i++) { 
    int value = 1023 - analogRead(analog_pins[i]);

    if(value<1000) Serial.print(" ");
    if(value<100) Serial.print(" ");
    if(value<10) Serial.print(" ");
    Serial.print(value);
    Serial.print(", ");
    
    if(i==0) { R = value/4; }
    if(i==1) { G = value/4; }
    if(i==2) { B = value/4; }
  }    // */  

  for(uint16_t i=numOfPx-1; i>0; --i) {
    strip.setPixelColor(i, strip.getPixelColor(i-1));
  }

  delay(10);

  int R = 255-(analogRead(A0)/4);
  int G = 255-(analogRead(A1)/4);
  int B = 255-(analogRead(A2)/4);
  uint32_t colorSelect = strip.Color( R, G, B);;
  
  strip.setPixelColor(0, colorSelect);
  strip.show();
}

Prezentacja prototypu:
Obrazek Obrazek Obrazek Obrazek
Oraz film demonstrujący działanie konwertera - porównanie z taśmą RGB i odbiornikiem RGBW.
http://filmy.elektroda.net/93_1492617607.mp4


Możliwości rozwoju:
-> Dodanie buforów wejściowych umożliwiających jednoczesne podłączenie do sterownika zwykłej taśmy RGB 12/24V i konwertera.
-> Przeróbka programu tak by odczytywał wygnały PWM zamiast uśrednionych wartości analogowych.
-> Dodanie odbiornika 2.4GHz i obsługi pilotów MiLight RGBW, a w przyszłości może RGB+CCT.
-> Miniaturyzacja urządzenia i przesiadka na mniejszy mikroprocesor np. ATTiny85 na płytce Digispark lub Trinket.


Ostatnią modyfikację chciałem wykonać ale odpuściłem ponieważ nie mam w zapasach gołego procesora ATTiny85 a płytka prototypowa którą dysponuję ma tylko jeden wolny kanał ADC (jeden zabiera reset, pozostałe dwa są zepsute przez rezystory i diody zenera przyłączone do USB).

Awatar użytkownika
kayron
Użytkownik
Posty: 2066
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 22 kwie 2017, 15:21

A ja nie rozumiem takiego podejścia ? Po co budować jakieś dziwne konwertery, jak diody sterowane są cyfrowo. Tak naprawdę moim zdaniem inwestowanie w takie diody, żeby zmieniać im tylko kolory na całej długości to bzdura. Mocą takiego zestawu LED RGB jest możliwość wyświetlania tak naprawdę efektów wizualnych, np. efektu wody, płomieni itp. i dopiero taki sterownik ma sens budować.

Awatar użytkownika
Ertew
Użytkownik
Posty: 1418
Rejestracja: 03 lip 2005, 10:36
Lokalizacja: Leszno
Kontakt:

Post autor: Ertew » 23 kwie 2017, 21:48

Wbrew pozorom taśma WS2811 ma kilka zalet np. stabilizacja prądu LED (spadek napięcia na długości taśmy nie powoduje rozrzutu kolorów), a za pomocą jednego uC i bramek NOT mogę sterować dowolną długością taśmy LED (ogranicza mnie moc zasilacza i poprowadzenie masy).

Mimo to zgadzam się z Tobą, sprowadziłem drogą taśmę LED do roli 2-3krotnie tańszej taśmy RGB. Zrobiłem to ponieważ kupiłem taśmę na zapas właśnie z myślą o jakiś efektach wizualnych, a bez pilota nie ma sensu tworzyć efekty i odtwarzać je w pętli do odcięcia zasilania. Bez sensu jest też rzucenie taśmy w kąt gdy mam jak ją wykorzystać.

Awatar użytkownika
kayron
Użytkownik
Posty: 2066
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 25 kwie 2017, 8:06

Cóż najpierw trzeba by po eksperymentować co taka taśma umie, i jakie są efekty, potem zrobić sterownik najlepiej z zdalnym dostępem, po Wi-fi lub bluetof i gitara.
Ja widzę w sumie 2 opcje:
1. Arduino
2. Rasppery Pi Zero lub jaki jego mini klon, Małe, ma kartę Sd na pokładzie USB.LAN wifi.

Awatar użytkownika
Ertew
Użytkownik
Posty: 1418
Rejestracja: 03 lip 2005, 10:36
Lokalizacja: Leszno
Kontakt:

Post autor: Ertew » 25 kwie 2017, 18:30

Akurat rPi zero w wersji jednordzeniowej odpada. rPi nie ma peryferiów umożliwiających sterowanie taśmą, a przerzucenie czarnej roboty (machanie pinem GPIO) na CPU ma sens tylko gdy system operacyjny nie będzie przeszkadzał.
Jeśli koniecznie ma być rPi to lepiej zastosować taśmę z wejściem SPI albo konwerter RS->LED na jakimś arduino (patrz projekt glediator) lub SPI->LED na bramkach i obwodach czasowych.

Jeśli nie trzymamy się rPi to lepiej iść w kierunku uC z wspomaganiem w postaci DMA (STM32 - http://www.elektroda.pl/rtvforum/topic3280019.html , Xmega czy PIC) albo popularne ESP8266 które po wyłączeniu WiFi mają aż nadto mocy obliczeniowej na obsługę taśmy WS281x.

Podstawowe modele arduino też się nadają ale mają zbyt małą wydajność by w trakcie wysyłania klatki obrazu pobrać kolejną klatkę z zewnętrznej pamięci, a co dopiero żeby wygenerować coś na podstawie algorytmu. To ogranicza prędkość odświeżania obrazu, co w moim przypadku akurat jest bez znaczenia.

r-mik
-
Posty: 48
Rejestracja: 10 wrz 2011, 6:36
Lokalizacja: Warszawa

Post autor: r-mik » 07 maja 2017, 20:32

Ertew pisze: Podstawowe modele arduino też się nadają ale mają zbyt małą wydajność by w trakcie wysyłania klatki obrazu pobrać kolejną klatkę z zewnętrznej pamięci
AVR ma wystarczająca moc. Nie ma problemu aby wysyłać dane do WS2812 na przerwaniach a program główny pobiera dane z zewnętrznej pamięci RAM. Oczywiście do sterowania WS2812 nie można w tym wypadku użyć SPI czy tym bardziej PIO.
Ertew pisze:Akurat rPi zero w wersji jednordzeniowej odpada. rPi nie ma peryferiów umożliwiających sterowanie taśmą
Czyli jakich peryferiów? Jest jakiś specjalny układ peryferyjny do sterowania WS2812 wbudowany w inne procesory tylko nie te w rPi? Co to za układ?
Ostatnio zmieniony 09 maja 2017, 16:19 przez r-mik, łącznie zmieniany 1 raz.

Awatar użytkownika
Ertew
Użytkownik
Posty: 1418
Rejestracja: 03 lip 2005, 10:36
Lokalizacja: Leszno
Kontakt:

Post autor: Ertew » 09 maja 2017, 17:14

WS2812 wymaga dość szczególnych zależności czasowych. Do sterowania idealnie sprawdzają się 'delikatnie spersonalizowane' peryferia poganiane przez system DMA. Oto przykłady:
STM32F030, SPI, timer, DMA: http://www.elektroda.pl/rtvforum/topic3280019.html
Teensy 3.0, 3x DMA: https://www.pjrc.com/teensy/td_libs_OctoWS2811.html
podobne sztuczki powinni się również udać na Xmegach.

W rPi nie znalazłem niczego podobnego, lecz nie twierdzę że się nie da. Gdyby się uprzeć to można przetłumaczyć każdy bit bufora obrazu na bajt "11100000" lub "11111000" i taki 8-krotnie większy bufor wysyłać za pomocą DMA i SPI / RS.

ODPOWIEDZ