Z zainteresowaniem przeczytałem "zajawkę" Kolegi Mirka odnośnie stosowania buforowania zapisu do LCD alfanumerycznego. Skąd wzięło się moje zainteresowanie?
Już tłumaczę. Często zdarza się, że po dłuższej pracy urządzenia pod wpływem zakłóceń zewnętrznych na wyświetlaczu pokazują się "duszki", jakieś znaki w przypadkowym miejscu.
Wyświetlacze zrealizowane na omawianym przez Mirka sterowniku charakteryzują się tym, że po wyświetleniu danego znaku jest on "zatrzaskiwany" na LCD aż do jego nadpisania innym znakiem.
Stąd często zachodzi konieczność nadmiarowego używania spacji do nadpisywania miejsc, które wg założeń powinny pozostać puste na wyświetlaczu. Istnieje także inny sposób, który omówię później wraz z jego wadami. Zatem zacznijmy nasze rozważania:
1)
ustawiam kursor w interesującej mnie pozycji:
Wypisuję na wyświetlacz tekst:
Tekst ma długość 9 znaków. I wszystko gra
Mamy nasze powitanie na wyświetlaczu. Tylko co się stanie w przypadku pojawienia się "duszka" na pozycji np 13 ? Jeżeli tak się złoży, że w programie nie używam pozycji 9-16, to taki "duszek znikąd" będzie sobie siedzieć na wyświetlaczu tak długo, aż nie użyję komendy LCDcls();. Można ten problem wyeliminować stosując dopełnienie spacjami:
Tylko czy takie podejście ma jakikolwiek sens jeżeli w programie używamy kilkudziesięciu komunikatów? Te "czyszczące duszki" spacje to niesamowite marnotrawienie pamięci mikrokontrolera
2)
Nieco inaczej sprawa wygląda, gdy w pętli głównej cały czas wyświetlam sobie jakiś napis:
A przy użyciu np. timera programowego co 100 lub 200ms wywołuję funkcję LCDcls();
I wszystko niby gra
Na ekranie nie ma już żadnych śmieci, co więcej: teraz można już dynamicznie zmieniać teksty na wyświetlaczu:
spowoduje wyswietlenie tekstu "nowy"
W poprzednim przypadku wyswietlony zostałby "nowyo LCD". No chyba, że wyświetlilibyśmy coś takiego:
czyli nadpisalibyśmy wcześniejszy tekst spacjami.
I niby już wszystko gra
Ten sposób testowałem na wielu różnych wyświetlaczach i spisywał się znakomicie. Ma on jednak jedną istotną wadę:
wszystko jest ok dopóki patrzymy na wyświetlacz "na wprost". Wystarczy, że zmieni się kąt patrzenia np na 60 stopni... I co? I wtedy widać już jak na dłoni, że wyświetlacz jest cyklicznie czyszczony
I masz babo placek... Niby nic wielkiego, ale niektórym użytkownikom naszego urządzenia coś takiego może się nie spodobać. Pytanie: jak temu zaradzić? Tutaj właśnie odpowiedzią jest buforowanie danych do wyświetlenia w pamięci RAM mikrokontrolera i wyświetlanie dopiero tak przygotowanych danych
3)
Mirek przygotowuje zaawansowaną bibliotekę, która z punktu widzenia użytkownika będzie "przezroczysta". Oznacza to, że funkcjami wyświetlającymi informacje będziemy posługiwać się tak jak wcześniej robiliśmy to z funkcjami bezpośrednio zapisującymi do LCD. Subtelna różnica polega na tym, że zapis do LCD odbywać się będzie "w tle" - my cały czas operujemy tylko na pamięci RAM.
Jak to wygląda w praktyce? Ano załóżmy, że na pozycji 1 linii pierwszej chcemy mieć na stałe wyświetlony jakiś komunikat. Zaś na pozycji np. 12 chcemy wyświetlać komunikat dynamiczny, mogący np. migać. Przy wykorzystaniu 2 poprzednich sposobów da się to osiągnąć, jednak będzie to:
a) pamięciożerne (nadpisywanie spacjami)
b) powodować może migotanie całego ekranu
Sposób Mirka pozwala zrealizować takie "animacje" bez najmniejszego problemu
W ramach ćwiczeń napisałem naprędce do bólu prosty i nieefektywny kod:
Kod absolutnie nie jest zoptymalizowany ani zbytnio zabezpieczony przed przekroczeniem zakresu tablicy, miał jedynie pokazać ideę wyświetlania buforowanego.
w głównej pętli programu na stałe wywoływane jest coś takiego:
i teraz z użyciem timera programowego powoduję miganie tekstu:
Przy czym dalsza część komunikatów wyświetlanych na LCD nie ulega jakimkolwiek zmianom, przekłamaniom itp. Nie występuje także efekt "duszków"
Rzecz jasna użyłem tutaj spacji do oczyszczania ekranu, jednak już we właściwej bibliotece obsługi będą do tego użyte pętle powodujące, że cała zawartość bufora różna od tej którą do niego zapisujemy będzie czyszczona. Podany powyżej przepis pozwolił mi na wspaniałe uzyskanie efektu migania fragmentu tekstu z jednoczesnym brakiem problemów z tekstem wyświetlanym "statycznie".
IMHO sposób Mirka jest nie tyle co wart uwagi - jest on wręcz niezbędny w zaawansowanych aplikacjach. Należy tu jednak mieć na uwadze przesiadkę ze sposobu liniowego programowania na programowanie "pseudo wielowątkowe". Taki tryb programowania stosowany jest powszechnie we wszelkiej maści sterownikach PLC. Przykładem niech będzie funkcja opóźnionego załączenia: w programowaniu liniowym funkcja taka na dłuzszy czas zablokowałaby przetwarzanie reszty programu. W sterowniku PLC deklaruję gotowy blok takiej funkcji, inicjuję ją sygnałem wejściowym a reszta mnie nie interesuje. Program się przetwarza a po jakimś czasie otrzymuję na wyjściu bloku sygnał o zakończeniu odmierzania czasu. W mikrokontrolerze niestety musimy samodzielnie opracować tego typu funkcję (jak zresztą wszystkie inne funkcje działające "wątkowo"). Zatem potrzebna jest zmiana przyzwyczajeń programistycznych, niektórych nawyków. Przede wszystkim potrzebna jest permanentna zmiana podejścia do "ciała" programu. W efekcie możliwe są do uzyskania zarówno efekty prezentowane w książce Mirka (rozdział "wprowadzenie do systemów czasu rzeczywistego") jak i wiele innych, znacznie bardziej zaawansowanych.
Mam nadzieję, że moje przydługie opracowanie będzie zachętą dla wielu malkontentów nazywających takie sposoby "przerostem formy nad treścią"... Takim przerostem jest propozycja zastosowania FreeRTOSa dla przysłowiowego "mrygania diodą": https://www.elektroda.pl/rtvforum/topic2239451.html#10634041 Opisywane w tej dyskusji zagadnienie jest tak banalnie proste do wykonania, że aż głupio tutaj nawet wspominać o RTOS
Jednak wielu programistów przyzwyczajonych do programowania liniowego nie widzi niestety innego wyjścia z sytuacji...
Konkludując: programowanie "wątkowe" jest znacznie trudniejsze od liniowego. Jednak warto po nie sięgnąć ze względu na korzyści jakie daje.
Zdaję sobie sprawę, że ten temat może wywołać "burzę" wśród zwolenników i przeciwników takiego podejścia. Chciałbym jednak, aby dyskusja przerodziła się we wzajemną wymianę doświadczeń, zarówno tych pozytywnych jak i negatywnych. Sam na codzień zawodowo zajmuję się programowaniem sterowników przemysłowych w języku ST. Tam "multiwątkowość" to chleb powszedni. Jednak, jak się okazuje, przy odpowiednim podejściu do zagadnienia z naszych poczciwych 8-io bitowych AVRków też można "wycisnąć" znacznie więcej niż programując liniowo. Kwestia dobrego zrozumienia tematu
Aktualnie cały czas uczę się języka C i mikrokontrolerów AVR, jednak jestem już na taki etapie (dodatkowo doświadczenia z pracy z systemami Real Time), że sam zauważam potencjał drzemiący w odpowiednim podejściu do programowania AVR.
Zapraszam Kolegów do dyskusji
PS: temat ten to w żadnym wypadku nie jest reklama Kolegi Mirekk36 ani firmy którą reprezentuje. Proszę zatem o darowanie sobie tekstów w stylu "promujesz kogoś" itp. Recenzję książek Koleków Mirekk36 i tmf można przeczytać tutaj.
Już tłumaczę. Często zdarza się, że po dłuższej pracy urządzenia pod wpływem zakłóceń zewnętrznych na wyświetlaczu pokazują się "duszki", jakieś znaki w przypadkowym miejscu.
Wyświetlacze zrealizowane na omawianym przez Mirka sterowniku charakteryzują się tym, że po wyświetleniu danego znaku jest on "zatrzaskiwany" na LCD aż do jego nadpisania innym znakiem.
Stąd często zachodzi konieczność nadmiarowego używania spacji do nadpisywania miejsc, które wg założeń powinny pozostać puste na wyświetlaczu. Istnieje także inny sposób, który omówię później wraz z jego wadami. Zatem zacznijmy nasze rozważania:
1)
ustawiam kursor w interesującej mnie pozycji:
Kod: text
Wypisuję na wyświetlacz tekst:
Kod: text
Tekst ma długość 9 znaków. I wszystko gra
Kod: text
Tylko czy takie podejście ma jakikolwiek sens jeżeli w programie używamy kilkudziesięciu komunikatów? Te "czyszczące duszki" spacje to niesamowite marnotrawienie pamięci mikrokontrolera
2)
Nieco inaczej sprawa wygląda, gdy w pętli głównej cały czas wyświetlam sobie jakiś napis:
Kod: text
A przy użyciu np. timera programowego co 100 lub 200ms wywołuję funkcję LCDcls();
Kod: text
I wszystko niby gra
Kod: text
spowoduje wyswietlenie tekstu "nowy"
Kod: text
czyli nadpisalibyśmy wcześniejszy tekst spacjami.
I niby już wszystko gra
wszystko jest ok dopóki patrzymy na wyświetlacz "na wprost". Wystarczy, że zmieni się kąt patrzenia np na 60 stopni... I co? I wtedy widać już jak na dłoni, że wyświetlacz jest cyklicznie czyszczony
I masz babo placek... Niby nic wielkiego, ale niektórym użytkownikom naszego urządzenia coś takiego może się nie spodobać. Pytanie: jak temu zaradzić? Tutaj właśnie odpowiedzią jest buforowanie danych do wyświetlenia w pamięci RAM mikrokontrolera i wyświetlanie dopiero tak przygotowanych danych
3)
Mirek przygotowuje zaawansowaną bibliotekę, która z punktu widzenia użytkownika będzie "przezroczysta". Oznacza to, że funkcjami wyświetlającymi informacje będziemy posługiwać się tak jak wcześniej robiliśmy to z funkcjami bezpośrednio zapisującymi do LCD. Subtelna różnica polega na tym, że zapis do LCD odbywać się będzie "w tle" - my cały czas operujemy tylko na pamięci RAM.
Jak to wygląda w praktyce? Ano załóżmy, że na pozycji 1 linii pierwszej chcemy mieć na stałe wyświetlony jakiś komunikat. Zaś na pozycji np. 12 chcemy wyświetlać komunikat dynamiczny, mogący np. migać. Przy wykorzystaniu 2 poprzednich sposobów da się to osiągnąć, jednak będzie to:
a) pamięciożerne (nadpisywanie spacjami)
b) powodować może migotanie całego ekranu
Sposób Mirka pozwala zrealizować takie "animacje" bez najmniejszego problemu
Kod: text
Kod absolutnie nie jest zoptymalizowany ani zbytnio zabezpieczony przed przekroczeniem zakresu tablicy, miał jedynie pokazać ideę wyświetlania buforowanego.
w głównej pętli programu na stałe wywoływane jest coś takiego:
Kod: text
i teraz z użyciem timera programowego powoduję miganie tekstu:
Kod: text
Przy czym dalsza część komunikatów wyświetlanych na LCD nie ulega jakimkolwiek zmianom, przekłamaniom itp. Nie występuje także efekt "duszków"
Rzecz jasna użyłem tutaj spacji do oczyszczania ekranu, jednak już we właściwej bibliotece obsługi będą do tego użyte pętle powodujące, że cała zawartość bufora różna od tej którą do niego zapisujemy będzie czyszczona. Podany powyżej przepis pozwolił mi na wspaniałe uzyskanie efektu migania fragmentu tekstu z jednoczesnym brakiem problemów z tekstem wyświetlanym "statycznie".
IMHO sposób Mirka jest nie tyle co wart uwagi - jest on wręcz niezbędny w zaawansowanych aplikacjach. Należy tu jednak mieć na uwadze przesiadkę ze sposobu liniowego programowania na programowanie "pseudo wielowątkowe". Taki tryb programowania stosowany jest powszechnie we wszelkiej maści sterownikach PLC. Przykładem niech będzie funkcja opóźnionego załączenia: w programowaniu liniowym funkcja taka na dłuzszy czas zablokowałaby przetwarzanie reszty programu. W sterowniku PLC deklaruję gotowy blok takiej funkcji, inicjuję ją sygnałem wejściowym a reszta mnie nie interesuje. Program się przetwarza a po jakimś czasie otrzymuję na wyjściu bloku sygnał o zakończeniu odmierzania czasu. W mikrokontrolerze niestety musimy samodzielnie opracować tego typu funkcję (jak zresztą wszystkie inne funkcje działające "wątkowo"). Zatem potrzebna jest zmiana przyzwyczajeń programistycznych, niektórych nawyków. Przede wszystkim potrzebna jest permanentna zmiana podejścia do "ciała" programu. W efekcie możliwe są do uzyskania zarówno efekty prezentowane w książce Mirka (rozdział "wprowadzenie do systemów czasu rzeczywistego") jak i wiele innych, znacznie bardziej zaawansowanych.
Mam nadzieję, że moje przydługie opracowanie będzie zachętą dla wielu malkontentów nazywających takie sposoby "przerostem formy nad treścią"... Takim przerostem jest propozycja zastosowania FreeRTOSa dla przysłowiowego "mrygania diodą": https://www.elektroda.pl/rtvforum/topic2239451.html#10634041 Opisywane w tej dyskusji zagadnienie jest tak banalnie proste do wykonania, że aż głupio tutaj nawet wspominać o RTOS
Konkludując: programowanie "wątkowe" jest znacznie trudniejsze od liniowego. Jednak warto po nie sięgnąć ze względu na korzyści jakie daje.
Zdaję sobie sprawę, że ten temat może wywołać "burzę" wśród zwolenników i przeciwników takiego podejścia. Chciałbym jednak, aby dyskusja przerodziła się we wzajemną wymianę doświadczeń, zarówno tych pozytywnych jak i negatywnych. Sam na codzień zawodowo zajmuję się programowaniem sterowników przemysłowych w języku ST. Tam "multiwątkowość" to chleb powszedni. Jednak, jak się okazuje, przy odpowiednim podejściu do zagadnienia z naszych poczciwych 8-io bitowych AVRków też można "wycisnąć" znacznie więcej niż programując liniowo. Kwestia dobrego zrozumienia tematu
Zapraszam Kolegów do dyskusji
PS: temat ten to w żadnym wypadku nie jest reklama Kolegi Mirekk36 ani firmy którą reprezentuje. Proszę zatem o darowanie sobie tekstów w stylu "promujesz kogoś" itp. Recenzję książek Koleków Mirekk36 i tmf można przeczytać tutaj.

