Skocz do zawartości

ArduinoUno sterowania listwami/taśmami LED


Sylba

Pomocna odpowiedź

Napisałem prosty program, którego zadaniem jest wyświetlaniu na ośmioelementowej listwie LED dowolnego wzoru i jego przesuwanie.

//Dołączenie biblioteki obsługującej linijkę led
#include <Adafruit_NeoPixel.h>  

//dedklaracja pinów i stałych
const int ledPin = A0;
const int ledCount = 8; //ilość LED w linijce
const int patCount = 3; //ilość elementów wzoru do wyświetlania

//deklaracja tablicy wyświetlanego wzoru
unsigned long pattern[patCount];
bool start = true; //flaga używana w instrukcji if , start = true dla początkowego wzoru, start = false dla kolejnych wzorów

//Konfiguracja linijki
Adafruit_NeoPixel linijka = Adafruit_NeoPixel(ledCount, ledPin, NEO_GRB + NEO_KHZ800);


void setup() {
  //Inicjalizacja linijki
  linijka.begin();
  linijka.show();
}

void loop() {  
  //definiowanie wyświetlanego wzoru
  unsigned long red = linijka.Color(30, 0, 0);
  unsigned long blue = linijka.Color(0, 0, 30);
  unsigned long green = linijka.Color(0, 30, 0);
  unsigned long magenta = linijka.Color(30, 0, 30);
  unsigned long pattern[patCount];  // ponowna deklaracja, bez której program nie działa

  if (start) {
    //wypełnienie linijki kolejnymi elementami wzoru
    unsigned long pattern[] = {blue, blue, red};
    for (int id = 0; id < ledCount; id=id+patCount) {
      for (int m = 0; m < patCount; m++) {
      linijka.setPixelColor(m+id, pattern[m]);
      }
    }
    //wyświetlenie linijki
    linijka.show();
    delay(150);
    start = false;
  }
  else {
    //zmiana wzoru - przesunięcie o jeden element w górę, element ostatni staje się pierwszym
    unsigned long tempVal = pattern[patCount-1];
    for (int i=patCount-1; i>0; i--) {
      pattern[i] = pattern[i-1];
    }
    pattern[0]=tempVal; 
    //wypełnienie linijki kolejnymi elementami wzoru   
    for (int id = 0; id < ledCount; id=id+patCount) {
      for (int m = 0; m < patCount; m++) {
        linijka.setPixelColor(m+id, pattern[m]);
      }
    }
    //wyświetlenie linijki
    linijka.show();
    delay(150);
  }
}

Program nie jest skomplikowany, wymaga zdefiniowania kolorów:

  //definiowanie wyświetlanego wzoru
  unsigned long red = linijka.Color(30, 0, 0);
  unsigned long blue = linijka.Color(0, 0, 30);
  unsigned long green = linijka.Color(0, 30, 0);
  unsigned long magenta = linijka.Color(30, 0, 30);

zadeklarowania w tablicy pattern:

    unsigned long pattern[] = {blue, blue, red};

przypisania kolejnym LED elementów wzoru:

    for (int id = 0; id < ledCount; id=id+patCount) {
      for (int m = 0; m < patCount; m++) {
      linijka.setPixelColor(m+id, pattern[m]);
      }
    }

wyświetlenia:

    linijka.show();
    delay(150);

Funkcję ruchu uzyskałem dzięki zmianie wzoru - przesuwając elementy o jeden tzn.: pierwszy staje się drugim, drugi - trzecim, a ostatni - pierwszym:

    unsigned long tempVal = pattern[patCount-1];
    for (int i=patCount-1; i>0; i--) {
      pattern[i] = pattern[i-1];
    }
    pattern[0]=tempVal; 

oraz ponownemu przypisaniu elementom LED kolejnych elementów nowego wzoru i wyświetleniu:

    //wypełnienie linijki kolejnymi elementami wzoru   
    for (int id = 0; id < ledCount; id=id+patCount) {
      for (int m = 0; m < patCount; m++) {
        linijka.setPixelColor(m+id, pattern[m]);
      }
    }
    //wyświetlenie linijki
    linijka.show();
    delay(150);

Nic nadzwyczajnego, ale uruchamiając program napotkałem kilka istotnych problemów. 
Najważniejszy, to deklaracja zmiennych i ich zasięg. Aż się prosi by fragment przypisywania elementom LED elementów wzoru i wyświetlenie wstawić do odrębnej funkcji:

	//wypełnienie linijki kolejnymi elementami wzoru
    unsigned long pattern[] = {blue, blue, red};
    for (int id = 0; id < ledCount; id=id+patCount) {
      for (int m = 0; m < patCount; m++) {
      linijka.setPixelColor(m+id, pattern[m]);
      }
    }
    //wyświetlenie linijki
    linijka.show();
    delay(150);

Jednak gdy to zrobiłem, okazało się, że kompilator nie zgłaszał błędu, ale zapisany wzór nie był wyświetlany.
Podobnie prosi się, by fragment funkcji void loop():

  //definiowanie wyświetlanego wzoru
  unsigned long red = linijka.Color(30, 0, 0);
  unsigned long blue = linijka.Color(0, 0, 30);
  unsigned long green = linijka.Color(0, 30, 0);
  unsigned long magenta = linijka.Color(30, 0, 30);
  unsigned long pattern[patCount];  // ponowna deklaracja, bez której program nie działa

który właściwie mógłby być wykonywany tylko raz, umieścić w void setup(). Próba umieszczenia tego fragmentu do setup także kończyła się błędami kompilacji.

Czy mógłby ktoś bardziej biegły w programowaniu powiedzieć, co jest nie tak i skąd błędy w kompilacji i sygnalizowanie błędów zasięgu zmiennych? Co trzeba zrobić by powtarzające się fragmenty zapisać w funkcji?
 

 


 

Link do komentarza
Share on other sites

Nie wierzą, że nie ma bardziej biegłych, ale Ok.

Dla uściślenia temat dotyczy układu z kursu Arduino II. Układ testowy złożony wg zamieszczonego w kursie schematu:

ardKur_II_2_diody_2.thumb.png.e02febe78e13b6f51b53330c6074af16.png

Żeby nie zostawiać otwartego tematu zgłębiłem bibliotekę Adafruit_NeoPixel.h oraz zamieszczone w niej przykłady. A to rezultat:

//FORBOT KURS ARDUINO II

//dołączenie biblioteki, definicja pinów, utworzenie obiektu linijka
#include <Adafruit_NeoPixel.h>

#define ledPin A0
#define ledCount 8

Adafruit_NeoPixel linijka(ledCount, ledPin, NEO_GRB + NEO_KHZ800);

//deklaracje kolorów oraz wyświetlanego wzoru - tablica pattern[].
uint32_t red = linijka.Color(255, 0, 0);
uint32_t green = linijka.Color(0, 255, 0);
uint32_t blue = linijka.Color(0, 0, 255);
uint32_t magenta = linijka.Color(255, 0, 255);
uint32_t black = linijka.Color(0, 0, 0);
uint32_t white = linijka.Color(255, 255, 255);
uint32_t pattern[] = {red, blue, green};
int patCnt = 3; //ilość elementów w tablicy pattern[]

void setup() {
  // ustawienia startowe
  linijka.begin();
  linijka.show();
  linijka.setBrightness(50);  //ustawienie jasności świecenia wszystkich LED od 0 do 255
}

void loop() {
  //wyzerowanie wszystkich diod linijki i uruchomienie funkcji patternUp
  //funkcja wypełnia linijkę wzorem z tablicy pattern[] i przesuwa go do góry
  linijka.clear();
  patternUp(pattern, 150);
}

//funkcja patternUp wypełnia linijkę wzorem pat[] i przesuwa wzór do góry
// int wait określa prędkość przemieszczania - im wartość większa tym wolniejsze zmiany
void patternUp(uint32_t pat[], int wait) {

  //deklaracja i tworzenie kopii roboczej tablicy pattern
  uint32_t patternCopy[patCnt]; 

  for (int patId=0; patId<patCnt; patId++) {
    patternCopy[patId] = pattern[patId];
  }


  for (int i = 0; i < patCnt; i++) {

    //wypełnianie linijki wzorem
    int m = 0;
    for (int n = 0; n < ledCount; n++) {
      linijka.setPixelColor(n, patternCopy[m]);
      m++;
      if (m==patCnt) {        
        m=0;
      }
    }

    //wyświetlanie wpisanego w linijkę wzoru
    linijka.show();
    delay(wait);  //spowolnienie - ustawienie szybkości przemieszczania wzoru

    //zmiana wzoru do wyświetlenia w kolejej rundzie. Zmian jest tyle ile elementów wzoru
    uint32_t tempCol = patternCopy[patCnt-1];
    for (int cnt=patCnt-1; cnt>0; cnt--) {
      patternCopy[cnt]=patternCopy[cnt-1];
    }
    patternCopy[0]=tempCol;
  }
}

Przy okazji przekonałem się jak ważne są tajemnicze zmienne typu uint32_t. W pierwszej wersji do zapisu kolorów pikseli led zastosowałem zmienne typu unsigned long, czterobajtowe zmienne pozwalające zapisać liczby całkowite od  0 do 4,294,967,295 (2^32 - 1). Skutkowało to tym, że po wykonaniu kilku pętli zadeklarowane kolory wzoru ulegały zmianie, a po kilkunastu pętlach nie przypominały w ogóle założonego wzoru. Zastosowanie zmiennych typu uint32_t, także przechowujących liczby całkowite, ale zawsze w formacie czterobajtowym, zapewniło stabilność kolorów.
Swoją tworzenie funkcji tworzących i animujących wzory na linijce i w ogóle na taśmach LED, to niezła zabawa. Warto poćwiczyć przed budową świątecznych dekoracji.

Link do komentarza
Share on other sites

Temat dość fajnie wpisuje się w to co ostatnio znalazłem na necie.

@Sylbaprzepraszam za wcięcie się w temat;) jednak bardzo nawiązuje jedno do drugiego.

Drogie chłopaki z Forbota, @H1M4W4R1 Ty piszesz aplikacje, a może nie trzeba aplikacji tylko sprytny kod wgrywany przez ota do esp32, co myślisz @ethanak?

Pytanie: jak zamienić prosty gif(?) np Mikołaja na obraz wyświetlany przez kurtynę z programowalnych led?

Drugie pytanie, jak mnie tego nauczyć?

 

 

Edytowano przez SOYER
Link do komentarza
Share on other sites

1 godzinę temu, SOYER napisał:

Pytanie: jak zamienić prosty gif(?) np Mikołaja na obraz wyświetlany przez kurtynę z programowalnych led?

W sumie rozwalić gifa na poszczególne klatki. Strzelam, że FFmpeg (zamiast gifa jakbyś miał film, to już na pewno da radę) da radę. Od biedy pewnie IrfanView. Ale jedno z ciekawszych narzędzi jakie ostatnio odkryłem do wsadowego przetwarzania obrazów, to ImageMagick. Jak masz klatki w chociażby łatwej do odczytu bitmapie, to albo gotowce skrypty/programy, albo sam je piszesz 😄, żeby zrobić sobie jakąś tablicę, czy cuś. Bitmapa nie jest taka straszna. Jedyne co, jak liczba bajtów wiersza nie będzie podzielna przez 4, to będą dodatkowe 1 do 3 bajtów, żeby było wyrównane to tych 32 bitów. Jak będzie za mało miejsca na klatki we flashu wybranej płytki, to SD. Ale jeśli nie jest to AVR/Arduino, to już wygrane. Jak jest biblioteka i API to wyświetlenia tablicy na programowalnych diodach, to już koniec. Byle obraz był pocięty i potem poskładany tak, jak zorganizowane są diody. GIF to pewnie 256 kolorów, ale konwersja na BMP przerobi go na 24 bity jak się za to dobrze zabierze. I tak są gotowe dane, które pójdą na diodę. Ta wersja za 300 Euro to ma raptem 1500 pikseli, więc tutaj pamięć nie będzie ograniczała mocno, no chyba, że Arduino...

  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

2 godziny temu, SOYER napisał:

Pytanie: jak zamienić prosty gif(?) np Mikołaja na obraz wyświetlany przez kurtynę z programowalnych led?

Określ szerokość/wysokość kurtyny, przeskaluj .gif na tą wartość i zapisz jako .raw (np. w gimp-ie), czyli plik, który ma format: 3 bajty (aka wartości RGB) * szer * wys. Przykładowo dla obrazu 200x200 pix dostajesz dokładnie 120k bajtów (3 * 200 * 200). Wszak to tylko przykład przerośniętej kurtyny z 40k diod (200x200), hehe. Później po kolei ustawiasz wartość RGB w buforze dla diod, a na koniec wyświetlasz. Na upartego można zrobić też animację, jeżeli pryndkości i zasobów wystarczy. W sumie to taki ekran z neopixelków.

Edytowano przez orb777
ófki
  • Lubię! 1
Link do komentarza
Share on other sites

6 godzin temu, orb777 napisał:

Później po kolei ustawiasz wartość RGB w buforze dla diod,

To dla mnie kluczowe, nie mam zielonego pojęcia jak ten „obrazek” włożyć do szkicu w postaci danych dla led…

1 godzinę temu, ethanak napisał:

@SOYER załóż oddzielny wątek to pogadamy. Zacznij od rozmiaru kurtyny i jakiej płytki chcesz użyć.

 

tak zrobię, widzę, że jest kilku bystrzaków którzy wiedzą o co chodzi.

@Sylba jeszcze raz przepraszam za wcinkę.

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.