Skocz do zawartości

Kurs STM32L4 – #15 – diody RGB WS2812B (liczniki), quiz


Komentator

Pomocna odpowiedź

Chodzi mi o fragment :

if(value & 0x80)

Rozumiem, że wynik tego warunku będzie pozytywny jeśli bitowo value = 1 oraz 0x80 = 1 prawda? Tylko nie rozumiem właśnie kiedy 0x80 będzie pozytywne.

Link do komentarza
Share on other sites

14 godzin temu, Kenny napisał:

Chodzi mi o fragment :

if(value & 0x80)

W tym przypadku "&" jest operatorem bitowym, który oznacza koniunkcję. Więcej na ten temat np. tutaj: https://pl.wikipedia.org/wiki/Koniunkcja_(logika)

Oznacza to, że wartość zmiennej value jest porównywana z liczbą 0x80 bit po bicie. Czyli w praktyce należy zacząć od zapisania wartości zmiennych w systemie binarnym. Załóżmy, że najpierw sprawdzamy przypadek, gdy zmienna value ma wartość zero:

0000 0000 (zmienna value o wartości 0)

1000 0000 (0x80 zapisane binarnie)

Teraz następuje porównanie bit po bicie. Idąc od lewej sprawdzamy pierwszy bit mamy 0 & 1, czyli fałsz. Dalej mamy same 0 w zmiennej 0x80, czyli zawsze będzie fałsz. Teraz kolejny przypadek:

1000 0000 (zmienna value o wartości 128)

1000 0000 (0x80 zapisane binarnie)

Idąc od lewej mamy 1 & 1, czyli prawdę. Pozostałe bity nie mają już znaczenia. Jaki z tego wniosek? Warunek będzie prawdziwy dla dowolnej wartości zmiennej value, której pierwszy bit będzie równy 1, czyli dla każdej liczby binarnej pasującej do wzoru 1XXX XXXX.

Daj znać czy to cos rozjaśniło. To temat związany raczej z samym C, a nie konkretnie z STM32 🙂 

  • Lubię! 1
  • Pomogłeś! 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

Dodaję właśnie LEDy WS2812B do projektu co prawda z STM32H7 ale funkcja HAL dla timera z DMA przyjmuje te same argumenty. Nie pamiętam jaki był stan w momencie pisania kursu, ale możliwe że jest drobny błąd w kursie.

Funkcja HAL przyjmuje wskaźnik na bufor:

/**
  * @brief  Starts the TIM PWM signal generation in DMA mode.
  * @param  htim TIM PWM handle
  * @param  Channel TIM Channels to be enabled
  *          This parameter can be one of the following values:
  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
  * @param  pData The source Buffer address.
  * @param  Length The length of data to be transferred from memory to TIM peripheral
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
                                        uint16_t Length)

Czyli tu jest błąd gdzie przekazujemy adres wskaźnika, ciekawe że działa:

HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, &test, sizeof(test));

Tu jest już ok, w burst też jest ok:

HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, (uint32_t*)led_buffer, sizeof(led_buffer));

Uważam też że nienajlepszym pomysłem jest dawanie sizeof(test) w ostatnim argumencie. Sizeof zwraca liczbę bajtów okupowaną przez tablicę lub rozmiar pointera gdyby wrzucić tablicę jako argument funkcji. Gorzej robi się gdy tak jak w STM32H7 minimalny rozmiar dla DMA to 16 bitów halfword, wtedy sizeof tablicy to 2xliczba elementów czyli nie to co trzeba wpisać w argumencie. IMO lepiej dać stałą albo podzielić przez sizeof(test[0]).

 

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

@Gienek O ile rozumiem chodzi Ci o &test ? Faktycznie można byłoby po prostu przekazać "test", bez & - pewnie zostało to z jakiegoś wcześniejszego kodu. Natomiast program działa poprawnie, bo jest poprawny... To taka ciekawostka, albo raczej paskudna cecha języka C. Adres tablicy jest taki sam jak sama tablica, czyli zarówno &test, jak i test ma taką samą wartość - chociaż różny typ. To nie jest adres wskaźnika, ale adres tablicy. Jednak tablice i wskaźniki to co innego, chociaż często wydają się tym samym.

Więcej o tym "fenomenie" podpowie wujek google, pierwszy lepszy link: https://stackoverflow.com/questions/2528318/how-come-an-arrays-address-is-equal-to-its-value-in-c

Natomiast co do DMA na bardziej zaawansowanych mikrokontrolerach to temat rzeka... Zapytam tylko podchwytliwie - jak dbasz o spójność pamięci cache podczas używania DMA na STM32H7?

 

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

@Elvis Ciekawe, tego nie wiedziałem. Zwracam honor 🙂 

18 godzin temu, Elvis napisał:

jak dbasz o spójność pamięci cache podczas używania DMA na STM32H7?

Na razie nie używam, to trudny temat.

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

Dnia 19.12.2021 o 13:21, adamnar napisał:

Witam. Rozwiązałem problem. Program funkcjonuje poprawnie po zmienieniu linijki 

  led_buffer[RESET_LEN + 24 * LED_N] = 100;

na

  led_buffer[RESET_LEN + 24 * LED_N] = 0;

Ogólnie, wydaje mi się, że w tym odcinku kursu znajduje się poważny błąd. Zaprezentowany sposób komunikacji z linijką led jest niezgodny z notą katalogową. Zacznijmy od następującego zdania:

Dlaczego? Po co potrzebne jest nam pełne wypełnienie? W nocie katalogowej nigdzie nie jest napisane że stan wysoki jest do czegokolwiek potrzebny. 

Następnie:

Dlaczego RESET jest na początku? W nocie katalogowej nie ma nic o stanie przed rozpoczęciem transmisji. Reset ma zostać wysłany PO zakończeniu transmisji. Czyli zgodnie z notą katalogową transmisja wygląda tak: 1) przesyłamy dane, 24 bitów na każdą diodę, 2) ustalamy stan NISKI na przynajmniej 50 us, 3) możemy wysłać kolejną transmisję. Tak więc ani robienie RESET na początku ani ustalanie 100% PWM na koniec nie ma sensu. 

Ten błędny model komunikacji jest potem ciągnięty przez cały artykuł, w efekcie zarówno kod podstawowy (przed utworzeniem biblioteki) jak i kod już po optymalizacji nie działają poprawnie. Zasugerowana przeze mnie zmiana wypełnienia z 100 na 0 sprawia, że urządzenie zaczyna działać poprawnie (najprawdopodobniej dlatego, że diody odebrały w końcu prawidłowy sygnał RESET na koniec komunikacji), choć kod nadal konceptualnie jest niepoprawny. 

Mi również pomogło, dzięki!  @adamnar

W moim przypadku skutkiem było "opóźnione" aktualizowanie się statusu pierwszej diody. W większości przypadków świeciła kolorem z "poprzedniego cyklu", podczas gdy wszystkie pozostałe diody miały poprawną, aktualną barwę. 
Dało się to obejść wstawianiem ws2812Wait() w specyficznych miejscach, ale dopiero zmiana ostatniej wartości bufora na 0 ostatecznie rozwiązała problem.

A odnośnie samego kursu, to klasa. Wielkie dzięki @Treker, za ich konsekwentne przygotowywanie. Przerobiłem Elektronikę, Arduino, kończę powoli STMa, a w w przyszłości pewnie spróbuję się zmierzyć z Raspberry. Nigdzie indziej nie widziałem wiedzy podanej w tak zbalansowany i kompleksowy sposób.
Rok temu byłem "inżynierem" mechaniki, który nie wiedział co to kondensator, a prawo Ohma to był dla mnie jakiś nieintuicyjny, dawno zapomniany wzór z wykładów. To jest niesamowite.

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

Dnia 20.01.2024 o 22:00, danitoWFD napisał:

Nigdzie indziej nie widziałem wiedzy podanej w tak zbalansowany i kompleksowy sposób.

@danitoWFD witam na forum i dziękuję za miłe słowa. Bardzo się cieszę, że kursy są pomocne! Powodzenia w dalszej nauce 🙂 

Link do komentarza
Share on other sites

Witam,

     Podczas tego kursu napotkałem trudności już na samym początku. Pod koniec sekcji "Pierwszy program obsługujący diody" wynikiem miała być dolna dioda świecąca na zielono. Gdy uruchomiłem program wszystkie diody świeciły na biało. Pierwsze co mi się nasunęło na myśl to polaryzacja PWM, jednak to nie rozwiązało problemu. Próbowałem zamieniać wartości wypełnienia, lecz to też nie pomogło. Przy różnych wartościach wypełnień, rozmiarów tablic, polaryzacji PWM oraz wszelkich kombinacji tych zabiegów udawało mi się doprowadzić do sytuacji, że dolna dioda nie świeciła w ogóle, a pozostałe na biało, lub losowe kolory losowych diod.

  HAL_TIM_Base_Start(&htim3);
  uint8_t test[40+7*24+1] = {0};
  for (int i=0;i<7*24;i++){
	  test[40+i]=32;
  }
  test[40] = 64;
  test[40+7*24] = 100;
  HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, &test, sizeof(test));

     Ostatecznie zauważyłem, że dioda bardzo się nagrzała. W związku z tym uznałem, nie mając innych pomysłów, że spróbuję użyć napięcia 3.3V i bezpośredniego połączenia sygnału PWM do diody. O dziwo sprawiło to, że zapaliła się jedna zielona dioda, jednak reszta świeciła na biało. Wtedy w programie zmieniłem ostatni element tablicy test na 0 zamiast 100 i zadziałało. Jednak co nadal jest dziwne, gdy go resetuję, otrzymuję wszystkie diody na biało, ponowny reset daje jedną diodę zieloną i tak na zmianę. Gdy nacisnę przycisk resetu dwa razy w krótkim czasie, otrzymuję na zmianę wszystkie diody na biało oraz jakiś losowy układ diod i ich kolorów. Uznałem, że może wiązać się to z kondensatorami. Gdy je usunąłem otrzymuję na zmianę zieloną diodę i wszystkie na biało po każdym resecie.

  HAL_TIM_Base_Start(&htim3);
  uint8_t test[40+7*24+1] = {0};
  for (int i=0;i<7*24;i++){
	  test[40+i]=32;
  }
  test[40] = 64;
  test[40+7*24] = 0;
  HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, &test, sizeof(test));

Mam w związku z tym dwa pytania: Dlaczego przykład w pierwszym akapicie może nie działać oraz jakim cudem przykład w drugim akapicie działa (w pewnym stopniu)?

Link do komentarza
Share on other sites

@akracz witam na forum 🙂 Mam propozycję - wykluczmy najpierw uszkodzenie diod RGB. Czy masz pod ręką Arduino? Jeśli tak to podłącz układ zgodnie z instrukcjami z kursu Arduino, sprawdź czy pasek diod działa poprawnie. Na Arduino szybciej wykluczymy problem sprzętowy. Grzanie się diody jest dość podejrzane. Informacje o podłączeniu tych diod do Arduino znajdziesz np. tutaj: https://forbot.pl/blog/kurs-arduino-ii-diody-rgb-tradycyjne-oraz-ws2812-id15495

Link do komentarza
Share on other sites

Przepraszam za tak późną odpowiedź, na majówce byłem poza domem i nie wziąłem arduino.

Na arduino działa wszystko zgodnie z oczekiwaniami, dioda jest włączona od kilku minut i tym razem się nie grzeje. Jednak w podesłanym kursie sygnał sterujący nie jest podłączony bezpośrednio, tylko przez rezystor 500 ohm, może to jest przyczyną takiego zachowania. Spróbuję dodać rezystor na STM32, jeśli to nie pomoże to będę jeszcze pisał

Link do komentarza
Share on other sites

(edytowany)

Znów piszę z opóźnieniem, mam trochę rzeczy na studia do zrobienia i dopiero dziś się zająłem kursem.

Dodanie rezystorów nic nie pomogło, dalej dioda zachowuje się niezdefiniowwanie. Gdy wgrywam program, dioda świeci cała na biało oraz się grzeje. Nie mam pojęcia co może być nie tak, kod i połączenie są 1:1

Edytowano przez akracz
Link do komentarza
Share on other sites

@akracz czy dioda nadal się grzeje? Bo to jest bardzo podejrzana sprawa 😉 Proponowałbym standardowo utworzyć projekt od zera i na spokojnie raz jeszcze przejść przez wszystkie etapy tworzenia projektu i kodu. Nikt inny w komentarzach nie zgłaszał ostatnio takiego problemu, więc jest bardzo duża szansa, że jednak problem leży gdzieś konkretnie w Twoim projekcie. Gdy zrobisz taką próbę i nadal nie będzie działało to wyeksportuj swój projekt i prześlij na forum jaki archiwum zip - sprawdzimy 🙂 

Link do komentarza
Share on other sites

(edytowany)

@Treker Dioda wciąż się grzeje, ale tylko gdy świeci cała na biało. Zachowuje się w sposób ciężki do zdefiniowania, czasem nie świeci, czasem świeci jakaś losowa kombinacja, często jest tak, że po wgraniu programu nic się nie dzieje, dopiero po odłączeniu sygnału sterującego pojawia się jakaś reakcja. Utworzyłem projekt od nowa, wydaje mi się, że wszystko jest na swoim miejscu. Nadal dioda zachowuje się inaczej niż powinna. przesyłam zipa, może jest coś co przeoczyłem

 

RGB_V2.zip

Edytowano przez akracz
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.