gohunoff Napisano Listopad 2, 2020 Udostępnij Napisano Listopad 2, 2020 (edytowany) Witam aktualnie razem z synem pracujemy nad lampką DIV (Led Cubes 4x4x4) Docelowo lampka ma mieć możliwość ustalenia do 10 różnych trybów wyświetlania, dodatkowo planujemy aby tryb wyświetlania był możliwy do zaprogramowania przez terminal Bluetooth z odpowiednią komendą (np. "set 1 0x0000x0660x0660x0000\n0x9009x0000x0000x9009\n") W tym celu przygotowałem stronę z wykorzystaniem obiektów Canvas JS, co pozwala na przygotowanie programu dla animacji (po klatkowej Cubs) i zabawę z lampką uprzyjemni. W załączniku ‘led_prog.zip’ kod strony do pobrania dla chętnych. Podczas projektu pojawił się problem z wyświetlaniem warstw diodów led, ze względu że diody w warstwie są podłączone do jednej masy, oczywiste jest że będzie problem z wyświetlaniem na różnych warstwach z różnym stanie Led np. W1 pali się W2 nie pali się. Problem rozwiązany został programowo , kolejne warstwy Led są wyświetlane w odstępie 2 milisekund dzięki czemu otrzymujemy złudzenie że cała kostka Led (klatka Led) jest aktywna w tym samym czasie. Dla rozjaśnienia poniżej kod programu. void loop() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; for (int i = 0; i < 4; i++) { DrawLayer(i); } if (roznicaCzasu >= AnimationRefresh) { zapamietanyCzas = aktualnyCzas; if (AnimationIndex<IndexK[AnimationSelect]) AnimationIndex++; else AnimationIndex=0; } } //rysujemy animacje dla odpowiedniej warstwy (i numer warstwy) void DrawLayer(int i) { unsigned int animation=ReadData(AnimationSelect,i); digitalWrite( LAYER_1, 0 ); digitalWrite( LAYER_2, 0 ); digitalWrite( LAYER_3, 0 ); digitalWrite( LAYER_4, 0 ); byte rows =ReadRows(animation,1); digitalWrite( LED_1, ReadLed(rows,1)); digitalWrite( LED_2, ReadLed(rows,2)); digitalWrite( LED_3, ReadLed(rows,3)); digitalWrite( LED_4, ReadLed(rows,4)); rows =ReadRows(animation,2); digitalWrite( LED_5, ReadLed(rows,1)); digitalWrite( LED_6, ReadLed(rows,2)); digitalWrite( LED_7, ReadLed(rows,3)); digitalWrite( LED_8, ReadLed(rows,4)); rows =ReadRows(animation,3); digitalWrite( LED_9, ReadLed(rows,1)); digitalWrite( LED_10, ReadLed(rows,2)); digitalWrite( LED_11, ReadLed(rows,3)); digitalWrite( LED_12, ReadLed(rows,4)); rows =ReadRows(animation,4); digitalWrite( LED_13, ReadLed(rows,1)); digitalWrite( LED_14, ReadLed(rows,2)); digitalWrite( LED_15, ReadLed(rows,3)); digitalWrite( LED_16, ReadLed(rows,4)); if (i==0) digitalWrite( LAYER_1, 255); else if (i==1) digitalWrite( LAYER_2, 255); else if (i==2) digitalWrite( LAYER_3, 255); else if (i==3) digitalWrite( LAYER_4, 255); delay(2); //wymagany w celu przedłurzenia czasu wyswietlania jednej warstwy 2 milisekundy } //PINY na ARDUINO #define LED_1 0 #define LED_2 1 #define LED_3 2 #define LED_4 3 #define LED_5 4 #define LED_6 5 #define LED_7 6 #define LED_8 7 #define LED_9 8 #define LED_10 9 #define LED_11 10 #define LED_12 11 #define LED_13 12 #define LED_14 13 #define LED_15 A4 #define LED_16 A5 //piny odwierzające kolejne warstwy animacji #define LAYER_1 A0 #define LAYER_2 A1 #define LAYER_3 A2 #define LAYER_4 A3 #include <stdlib.h> int PROGRAMSIZE = 10; //masymalny rozmiar animacji int PROGRAMMAX = 10; //masymalna liczba możliwych programuw do zaprogramowania //Bufor dla pamieci danych //jednka klataka zajmujew 2 bajty x 4 warstwy = 8 bajtów + 1 bajt index klatki = 9 bajtów unsigned int PROGRAM[10][4][10]; //900 bajtów unsigned IndexK[10]; int AnimationRefresh=1000; int AnimationSelect=0; //index wybranego programu int AnimationIndex=0; //index wybranej klatki w programie unsigned long aktualnyCzas = 0; unsigned long zapamietanyCzas = 0; unsigned long roznicaCzasu = 0; void ClearLed() { digitalWrite( LED_1, LOW ); digitalWrite( LED_2, LOW ); digitalWrite( LED_3, LOW ); digitalWrite( LED_4, LOW ); digitalWrite( LED_5, LOW ); digitalWrite( LED_6, LOW ); digitalWrite( LED_7, LOW ); digitalWrite( LED_8, LOW ); digitalWrite( LED_9, LOW ); digitalWrite( LED_10, LOW ); digitalWrite( LED_11, LOW ); digitalWrite( LED_12, LOW ); digitalWrite( LED_13, LOW ); digitalWrite( LED_14, LOW ); digitalWrite( LED_15, LOW ); digitalWrite( LED_16, LOW ); } void setup() { pinMode( LED_1, OUTPUT ); digitalWrite( LED_1, HIGH ); pinMode( LED_2, OUTPUT ); digitalWrite( LED_2, HIGH ); pinMode( LED_3, OUTPUT ); digitalWrite( LED_3, HIGH ); pinMode( LED_4, OUTPUT ); digitalWrite( LED_4, HIGH ); pinMode( LED_5, OUTPUT ); digitalWrite( LED_5, HIGH ); pinMode( LED_6, OUTPUT ); digitalWrite( LED_6, HIGH ); pinMode( LED_7, OUTPUT ); digitalWrite( LED_7, HIGH ); pinMode( LED_8, OUTPUT ); digitalWrite( LED_8, HIGH ); pinMode( LED_9, OUTPUT ); digitalWrite( LED_9, HIGH ); pinMode( LED_10, OUTPUT ); digitalWrite( LED_10, HIGH ); pinMode( LED_11, OUTPUT ); digitalWrite( LED_11, HIGH ); pinMode( LED_12, OUTPUT ); digitalWrite( LED_12, HIGH ); pinMode( LED_13, OUTPUT ); digitalWrite( LED_13, HIGH ); pinMode( LED_14, OUTPUT ); digitalWrite( LED_14, HIGH ); pinMode( LED_15, OUTPUT ); digitalWrite( LED_15, HIGH ); pinMode( LED_16, OUTPUT ); digitalWrite( LED_16, HIGH ); pinMode( LAYER_1, OUTPUT ); digitalWrite( LAYER_1, LOW ); pinMode( LAYER_2, OUTPUT ); digitalWrite( LAYER_2, LOW ); pinMode( LAYER_3, OUTPUT ); digitalWrite( LAYER_3, LOW ); pinMode( LAYER_4, OUTPUT ); digitalWrite( LAYER_4, LOW ); ClearLed(); AnimationRefresh=1000; AnimationIndex=0; AnimationSelect=0; for (int io=0;io<PROGRAMMAX;io++) ClearProgram(io); InsertAnimation(AnimationSelect,"0xFFFFx0000xFFFFx0000\n0x0000xFFFFx0000xFFFF\n"); InsertAnimation(1,"0x0000x0660x0660x0000\n0x9009x0000x0000x9009\n"); InsertAnimation(2,"0x8421x8421x8421x8421\n0x0C30x0C30x0C30x0C30\n0x03C0x03C0x03C0x03C0\n0x1248x1248x1248x1248\n0x2244x2244x2244x2244\n0x4422x4422x4422x4422\n"); InsertAnimation(3,"0xFFFFxFFFFx0660x0660\n"); AnimationSelect=1; } void ClearProgram(int nr) { for (int i=0;i<PROGRAMSIZE;i++) { PROGRAM[nr][0][i]=0x0000; PROGRAM[nr][1][i]=0x0000; PROGRAM[nr][2][i]=0x0000; PROGRAM[nr][3][i]=0x0000; } } String getValue(String data, char separator, int index) { int found = 0; int strIndex[] = { 0, -1 }; int maxIndex = data.length() - 1; for (int i = 0; i <= maxIndex && found <= index; i++) { if (data.charAt(i) == separator || i == maxIndex) { found++; strIndex[0] = strIndex[1] + 1; strIndex[1] = (i == maxIndex) ? i+1 : i; } } return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; } unsigned int toLayer(String value) { char ssid_array[5]; value.toCharArray(ssid_array, 5); long decimal_answer = strtol(ssid_array, NULL, 16); return decimal_answer; } void InsertAnimation(int nr,String value) { unsigned long vauleWord=0; ClearProgram(nr); int indexFream=0; PROGRAM[AnimationSelect]; for (int index=0;index<PROGRAMSIZE;index++) { int indexLayr=1; String objFream = getValue(value,'\n',index); if (objFream=="") break; String objLayr = getValue(objFream,'0x',indexLayr); //1 vauleWord = toLayer(objLayr); PROGRAM[nr][0][index] = vauleWord; indexLayr++; objLayr = getValue(objFream,'0x',indexLayr); //2 vauleWord = toLayer(objLayr); PROGRAM[nr][1][index] = vauleWord; indexLayr++; objLayr = getValue(objFream,'0x',indexLayr); //3 vauleWord = toLayer(objLayr); PROGRAM[nr][2][index] = vauleWord; indexLayr++; objLayr = getValue(objFream,'0x',indexLayr); //4 vauleWord = toLayer(objLayr); PROGRAM[nr][3][index] = vauleWord; indexFream++; } IndexK[nr]=indexFream-1; } //pobieramy odpowiednia klatkę animacji //NR - NMERA AKTUANIE WYBRANEJ ANIMACJI //index - INDEKS OKRESLAJACY AKTUALNY NUMER WYSWIETLANEJ KLATKI unsigned int ReadData(int nr,int i) { unsigned int aut=0x0000; aut = PROGRAM[nr][i][AnimationIndex]; return aut; } //pobieramy dane dla odpowiedniej warstwy - wiersz led byte ReadRows(unsigned int dane,int nrL) { switch (nrL) { case 1: return (0xF000 & dane) >> 12; case 2: return (0x0F00 & dane) >> 8; case 3: return (0x00F0 & dane) >> 4; case 4: return (0x000F & dane) ; default: return 0x0; } } //pobermy dane dla odpowiedniego led w wierszu bool ReadLed(byte dane,int nrLed) { switch (nrLed) { case 4: return (0b0001 & dane)>0; case 3: return (0b0010 & dane)>0; case 2: return (0b0100 & dane)>0; case 1: return (0b1000 & dane)>0; default: return false; } } Aktualnie zastanawiam się co wykorzystać w celu zwiększenia ilości pionów dla Arduino , Chodzi o fakt że Ledy są zasilane bezpośrednio z pionów cyfrowych Arduino (+) i zależy mi aby moc Ledów nie uległy zmianie (aby świeciły równomiernie). Proszę o sugestię… led_prog.zip filmy.zip Edytowano Listopad 3, 2020 przez gohunoff 1
Gość Listopad 3, 2020 Udostępnij Listopad 3, 2020 Mylales o rejestrze przesuwnym? 3 piny arduino obsługują wtedy 8 (i wielokrotność 8 przy zastosowaniu szeregowym większej ilości rejestrów) wyjsc
marek1707 Listopad 3, 2020 Udostępnij Listopad 3, 2020 Poza tym nie wiemy jak obecnie wyglądają połączenia Twojej megalampki z samym procesorem. Jego piny są dość słabe i przy multipleksowaniu 64 LEDów jasność może być marna, a co gorsza zmieniać się wraz liczbą jednocześnie świecących punktów. No a przecież planujesz zwiększyć jeszcze liczbę diodek (rodzaj żeński: dioda, diod, diody..) co może wymagać dodania driverów (np. tranzystorowych). Ograniczeniem jest nie tylko prąd pojedynczego pinu, ale także sumaryczny prąd przepływający przez wyprowadzenia VCC/GND kostki procesora. BTW: Łańcuchy typu: "0x8421x8421x8421x8421\n0x0C30x0C30x0C30x0C30\n0x03C0x03C0x03C0x03C0\n0x1248x1248x1248x1248\n0x2244x2244x2244x2244\n0x4422x4422x4422x4422\n" są przechowywane w RAMie procesorka. Nie programujesz PCta z praktycznie nieskończoną pamięcią tylko małe Arduino, które wszystkiego ma 2K a tą metodą zaraz cały dostępny RAM zapełnisz. Pomyśl o umieszczeniu tego rodzaju danych w pamięci programu. 1
gohunoff Listopad 3, 2020 Autor tematu Udostępnij Listopad 3, 2020 Dzięki za odpowiedz ogólnie wykorzystam rejestr przesuwny wydaje się najlepszym rozwiązaniem. marek1707 ja w programie ma zarezerwowaną tablicę unsigned int PROGRAM[10][4][10]; dzięki czemu mam możliwość do zaprogramowania 10 programów po 10 klatek animacji. Ja nie zapamiętuję stringów tylko będę konwertował obiekty przesyłane przez terminal Bluetooth do tej tabeli - metoda InsertAnimation Zależy mi na tym aby ta tablica była zarezerwowana zajmie ona sporo prawie 1k Ram ale będzie możliwe przeprogramowanie urządzenia z poziomu komórki i dodatkowo nie będzie wymaganie stałe połączenie z komórką w celu wyświetlania nowej animacji. Co do do portów wychodzących to mam dodane tranzystory na każdej z warstw (4 tranzystory BC547 - może za słabe), właściwe w celu żeby zabezpieczyć porty analogowe. Nie wiem jednak czy muszę koniecznie dodawać tranzystory na każde wiście cyfrowe. Dopiero zaczynam przygody e elektroniką wiec proszę wyrozumiałość.
marek1707 Listopad 3, 2020 Udostępnij Listopad 3, 2020 53 minuty temu, gohunoff napisał: Ja nie zapamiętuję stringów A myślisz, że skąd one się biorą jako argumenty dla InsertAnimation()? Obecnie siedzą w RAMie a funkcja dostaje wskaźniki do nich. Chyba, że w docelowej wersji nie będziesz nigdzie przechowywał stringów "startowych" a zawsze dosyłał je przez BT. Bo obecnie, w kodzie jaki zaprezentowałeś, mimo Twoich szczerych chęci trzymasz je w RAMie. Wyjściem jest inicjalizacja tablicy PROGRAM w miejscu jej definicji. Wtedy rzeczywiście, rozbiegówka C przepisuje zawartość początkową z FLASHa do RAMu jeszcze przed uruchomieniem main() czy tam startup(). 1 godzinę temu, gohunoff napisał: Co do do portów wychodzących to mam dodane tranzystory na każdej z warstw (4 tranzystory BC547 - może za słabe), właściwe w celu żeby zabezpieczyć porty analogowe. Tranzystory przynajmniej od strony elektrod wspólnych (czyli tam gdzie spływa sumaryczny prąd z każdej warstwy) to bardzo dobry pomysł. BC547 nie są za słabe - przynajmniej jeszcze nie w tej konstrukcji. Mogą być tylko za słabo sterowane, ale jeśli nie zauważasz przygaszania warstw w zależności od liczby jednocześnie załączonych na nich LEDów, to jest OK. "Porty analogowe" są w trybie wyjścia cyfrowego tak samo silne jak te normalnie cyfrowe, więc to nie jest kwestia "zabezpieczenia" a zwiększenia wydajności prądowej. Linie "Ax" mają dodatkowo funkcje wejść analogowych, ale to dodatek do ich normalnej działalności cyfrowej. 1 godzinę temu, gohunoff napisał: Nie wiem jednak czy muszę koniecznie dodawać tranzystory My też nie wiemy, bo nie wiemy co chcesz zrobić. Dopóki współczynnik multipleksowania (w tym przypadku liczba warstw) nie przekracza kilku, to wydajność prądowa pojedynczej linii portu cyfrowego wystarczy. Ale jeśli planujesz zrobienie np. 6 lub więcej warstw, to już bym się zastanowił nad rekonfiguracją całości, bo w ciągu dnia kostka może już wyglądać słabo (pomijając fakt, że zabraknie pinów procesora i i tak będziesz musiał dodać jakieś rozszerzenia). No kwestia jakości używanych LEDów. Jedne świecą dobrze przy 1mA prądu stałego a innym 20mA za mało by w ogóle je zauważyć. 1
Gość Listopad 4, 2020 Udostępnij Listopad 4, 2020 Jeśli chodzi o tranzystory to nigdy nie widziałem nigdy projektu tego typu bez nich. Uznałem, że są niezbędne lub z nimi jest dużo łatwiej. Rejest przesówny z którym się bawiłem to 74hc595. Jeśli potrzebujesz zrozumieć zasadę działania to służę pomocą
gohunoff Listopad 4, 2020 Autor tematu Udostępnij Listopad 4, 2020 wilq_89 dzięki ale znalazłem w necie na temat 74hc595 https://www.tranzystor.pl/artykuly-i-schematy/arduino/arduino-rejestr-przesuwny-74hc595.html Czekam teraz aktualnie na części, jak już przyjdą i zmodyfikuje projekt podzielę się informacjami o postępach. Przygotuje też schemat i wrzucę żeby widomo dokładnie jak zbudowany jest projekt.
Gość Listopad 4, 2020 Udostępnij Listopad 4, 2020 Fajnie, że po polsku. Z tym kodem się spotkałem chyba na oficjalnej stronie arduino. Średnio był pomocny w nauce .
Pomocna odpowiedź
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ę »