Jakiś czas temu trafiłem na stronę www.whiteelectronics.pl której autor jest polskim dystrybutorem budżetowych paneli operatorskich DGUS. Z ciekawości nabyłem jeden z tych wyświetlaczy (dokładnie ten), aby zapoznać się z jego możliwościami. Za niewielką cenę otrzymujemy kolorowy wyświetlacz z panelem dotykowym, który obsługujemy przy pomocy portu RS232 w standardzie TTL. Jeżeli chodzi o możliwości samego wyświetlacza to uważam, że za tę cenę jest to strzał w 10kę, aby móc konkurować z przemysłowymi panelami (ot choćby Micro Innowation) w aplikacjach o silnie okrojonym budżecie. Trochę czasu trzeba poświęcić na przyzwyczajenie się do dość minimalistycznego środowiska w którym tworzymy wizualizację i do jego ograniczeń (nie da się wprost zrobić pewnych czarów znanych mi z paneli serii XV-1xx, ale da się to osiągnąć stosując kilka prostych zabiegów). Jednak po jego opanowaniu (mi zajęło to 2 popołudnia) możemy z powodzeniem tworzyć efektownie wyglądające wizualizacje. Na podkreślenie zasługuje fakt świetnego wsparcia technicznego ze strony dystrybutora. Polecam również poszukać Jego artykułów na Elektrodzie - nick Bieli.
Do rzeczy: w każdym panelu operatorskim zmiennym nadawane są adresy. Niektóre z paneli potrafią zassać listę zmiennych i ich adresów bezpośrednio ze środowika w którym programujemy PLC (np. soft galileo importuje listę zmiennych utorzoną w Codesys). To bardzo przyspiesza pracę. Niestety my zmuszeni będziemy zarówno po stronie uP jak i panelu ręcznie ustawić adresy.
Aby moja biblioteka była jak najbardziej przyjazna postanowiłem, że:
- umieszczona będzie w niej jedna zmienna określająca ilość zmiennych jaką wymieniamy się z panelem,
- adresacja zmiennych w panelu nie musi być ciągła, tzn. każdy adres kolejnej zmiennej nie musi być adresem następującym bezpośrednio po poprzedniej,
- do panelu przesyłane będą tylko zmienne które uległy modyfikacji w uP,
- możliwe jest ustawienie interwału transmisji do wyświetlacza,
- na podstawie interwału wyznaczany jest czas timeout dla odczytu z wyświetlacza,
- biblioteka przygotowana jest do współpracy z procesorami Atmega w których występuje różne nazewnictwo rejestrów kontrolnych UART,
- każda wymieniana zmienna widziana będzie w uP jako: pojedyncza zmienna uint16_t, 2 zmienne uint8_t, 16 zmiennych bitowych - co umożliwia na prawdę elastyczne pisanie oprogramowania,
- z poziomu uP możliwe będzie przełączanie wyświetlanych ekranów,
- wprowadzona zostanie natywna obsługa RS485.
Nie będę się tutaj rozwodzić nt. sposobu adresacji zmiennych po stronie panelu - strona dystrybutora i jego wpisy na Elektrodzie wystarczająco wyczerpują to zagadnienie.
Zatem... Do dzieła!
Biblioteka znajduje się w katalogu Panel_DGUS. Podzielona jest na warstwę wysokopoziomową z której korzystamy w naszym programie, oraz niskopoziomową - opdowiedzialną za bezpośrednią współpracę z modułem UART. Plik DHUS.h zawiera deklaracje funkcji:
Ponadto w programie korzystać będziemy ze zmiennych typu strukturalnego "ZmienneDGUS[]". Zdefiniowane są one w plikach obsługi niskopoziomowej. Dzięki tak zadeklarowanej zmiennej mam w programie od razu bezpośredni dostęp do poszczególnych interesujących nas elementów:
- adresu zmiennej
- danych
Taki pojedynczy rekord opisujący zmienną uzyskałem dzięki stworzeniu "potworka":
Jest to unia zawierająca w swoim wnętrzu kilka struktur. Takie podejście pozwoliło na bezproblemowy dostęp do danych na kilka sposobów. Zawartość unii wymuszona jest przez kształt ramki przesyłanych do wyświetlacza danych. W obecnym kształcie uniemożliwia to wymianę z wyświetlaczem danych 32 bitowych, ale zrezygnowałem z tej możliwości świadomie, uznając ją za zbędną dla mnie.
Plik DGUS_UART_Config.h
W pliku tym znajdziemy szereg parametrów konfiguracyjnych biblioteki. Są to:
Dołożyłem starań, żeby inicjalizacja UART dla procesorów z dwoma UARTAMI była poprawna, jednak gdyby ktoś znalazł tu jakiś błąd to proszę dać znać.
Piszemy program!
Do pliku main includujemy plik DGUS.h. Przed główną pętlą programu wywołujemy funkcję inicjalizacji UART przypisanego dla naszego panelu.
Następnie podajemy adresy zmiennych jakie użyliśmy w panelu:
W moim przypadku adresacja jest ciągła (co 2 bajty - wynika to ze specyfikacji pamięci zmiennych panelu), ale zrobiłem tak tylko i wyłącznie dla własnej wygody. Adresacja nie musi być ciągła.
Teraz możemu już przystąpić do wymiany danych z panelem. Służą do tego 2 funkcje, które należy umieścić w głównej pętli programu:
Pierwsza z nich odpowiedzialna jest za przetworzenie odebranych z wyświetlacza danych. Zawiera w sobie mechanizm timeoutu na wypadek zaistnienia błędów w transmisji z wyświetlacza do systemu mikroprocesorowego.
Zadaniem drugiej jest zapisanie naszych zmiennych do panelu. Można by to wszystko zapisać razem w jednej funkcji, ale ze względu na specyficzne zastosowanie jakie miały u mnie ostatnio te funkcje postanowiłem, że będą one osobno. Obydwie funkcje pobierają jako argument wskaźnik na timer programowy (o timerach programowych możesz poczytać tutaj). Jak we wszystkich moich kodach, także i tutaj przyjęta została rozdzielczość timerów programowych wynosząca 10ms.
Jak widać powyżej potrzebujemy dwóch niezależnych timerów programowych.
Napisałem wcześniej, że uP wysyła do panelu jedynie te zmienne których wartość uległa zmianie od ostatniej wysyłki. Jest to jak najbardziej prawdą. Jednak funkcja ta ma pewną "furtkę" w postac przesłania o panelu pełnej listy zmiennych co określony czas. Wyobraźmy sobie sytuację,w której wyłączyliśmy zasilanie panelu bez wyłączania zasilanai systemu mikroprocesorowego. Nasz system wysyła sobie dane do panelu (a raczej nie wysyła jeżeli nie uległy zmianie). Jednak skąd u licha ma on wiedzieć, że panel został zrestartowany? Owszem można to rozwiązać odczytując statusy z rejestrów kontrolnych panelu. Jednak jest to dodatkowy nakład kodu, który moim zdaniem jest niepotrzebny. Wprowadziłem zatem prosty mechanizm, który cyklicznie co czas równy 255*CzasAktualizacjiZmiennychDGUS przesyła nam pełną listę zmiennych do panelu. Dzięki temu unikniemy sytuacji jaką opisałem powyżej.
A teraz dostęp do zmiennych:
- jako uint16_t
- jako uint8_t
- jako pojedyncze bity
Przestrzegam aby pamiętać, że maksymalny indeks tablicy zmiennych jaki możemy wybrać to IloscZmiennychDGUS-1, w przeciwnym wypadku poślemy nasz program w wieczną otchłań... Należy o tym pamiętać tworząc dowolne pętle indeksujące tablicę zmiennych.
Zastanawiałem się również nad implementacją mechanizmu odczytu numeru aktualnie wyświetlanego ekranu. Jednak w toku pisania programu zrezygnowałem z takiej możliwości uznając ja za (przynajmniej dla mnie) całkowicie zbędną. Wynika to z faktu, że tworząc wizualizację dokładnie znamy numery poszczególnych plansz i chcąc wyświetlić jakąś na ekranie po prostu podajemy jawnie jej numer. Jeżeli już zaistniałaby konieczność wykonania akcji związanej z przejściem do konkretnej planszy to skupiłbym się raczej na użyciu w wizualizacji opcji przełączenia planszy z wysłaniem jakiegoś numeru który jej przyporządkowujemy. Dzięki temu nie trzeba będzie rozbudowywać kodu po stronie mikrokontrolera - wystarczy jedną z wirtualnych zmiennych wymiany danych przeznaczyć na przechowywanie właśnie tej wspomnianej wartości.
Przykładowy kod zawiera funkcję main w postaci:
Jak widać wszystko jest jasne i przejrzyste. Patrząc na ciało funkcji main od razu wiemy co tak właściwie robimy w programie (bo zdarza się, że czasem sami tego nie wiemy...
hehe).
Praca z pacjentem...
Na mojej stronie zamieściłem gotowy, sprawdzony, działający przykład użycia biblioteki, oraz prostą wizualizację współpracującą z tym przykładem. W katalogu PROJEKT_DGUS znajduje się przykładowy projekt dla panelu DGUS o przekątnej 4,3". Projekt można otworzyć do edycji przy pomocy DGUS_SDK dostępnego na www.whiteelectronics.pl lub też użyć już przygotowanej wizualizacji. W tym celu należy przygotować kartę microSD o pojemności NIE WIĘKSZEJ niż 2GB, sformatować ją w systemie plików Fat32 a następnie skopiować na nią cały katalog DWIN_SET. Po włożeniu karty do wyświetlacza powinien on samoczynnie załadować jej zawartość. Jeżeli to nie nastąpi to należy wyłączyć i włączyć zasilanie wyświetlacza. Po wczytaniu wizualizacji kartę można trwale usunąć ze slotu, inaczej przy każdym restarcie wizualizacja będzie na nowo wczytywana.
Istnieje również możliwość wgrywania wizualizacji i parametrów konfiguracyjnych do panelu bezpośrednio z poziomu środowiska DGUS_SDK - wtedy karta nie jest nam wcale potrzebna.
Do rzeczy: w każdym panelu operatorskim zmiennym nadawane są adresy. Niektóre z paneli potrafią zassać listę zmiennych i ich adresów bezpośrednio ze środowika w którym programujemy PLC (np. soft galileo importuje listę zmiennych utorzoną w Codesys). To bardzo przyspiesza pracę. Niestety my zmuszeni będziemy zarówno po stronie uP jak i panelu ręcznie ustawić adresy.
Aby moja biblioteka była jak najbardziej przyjazna postanowiłem, że:
- umieszczona będzie w niej jedna zmienna określająca ilość zmiennych jaką wymieniamy się z panelem,
- adresacja zmiennych w panelu nie musi być ciągła, tzn. każdy adres kolejnej zmiennej nie musi być adresem następującym bezpośrednio po poprzedniej,
- do panelu przesyłane będą tylko zmienne które uległy modyfikacji w uP,
- możliwe jest ustawienie interwału transmisji do wyświetlacza,
- na podstawie interwału wyznaczany jest czas timeout dla odczytu z wyświetlacza,
- biblioteka przygotowana jest do współpracy z procesorami Atmega w których występuje różne nazewnictwo rejestrów kontrolnych UART,
- każda wymieniana zmienna widziana będzie w uP jako: pojedyncza zmienna uint16_t, 2 zmienne uint8_t, 16 zmiennych bitowych - co umożliwia na prawdę elastyczne pisanie oprogramowania,
- z poziomu uP możliwe będzie przełączanie wyświetlanych ekranów,
- wprowadzona zostanie natywna obsługa RS485.
Nie będę się tutaj rozwodzić nt. sposobu adresacji zmiennych po stronie panelu - strona dystrybutora i jego wpisy na Elektrodzie wystarczająco wyczerpują to zagadnienie.
Zatem... Do dzieła!
Biblioteka znajduje się w katalogu Panel_DGUS. Podzielona jest na warstwę wysokopoziomową z której korzystamy w naszym programie, oraz niskopoziomową - opdowiedzialną za bezpośrednią współpracę z modułem UART. Plik DHUS.h zawiera deklaracje funkcji:
Code: c
- adresu zmiennej
- danych
Taki pojedynczy rekord opisujący zmienną uzyskałem dzięki stworzeniu "potworka":
Code: c
Plik DGUS_UART_Config.h
W pliku tym znajdziemy szereg parametrów konfiguracyjnych biblioteki. Są to:
Code: c
Dołożyłem starań, żeby inicjalizacja UART dla procesorów z dwoma UARTAMI była poprawna, jednak gdyby ktoś znalazł tu jakiś błąd to proszę dać znać.
Piszemy program!

Do pliku main includujemy plik DGUS.h. Przed główną pętlą programu wywołujemy funkcję inicjalizacji UART przypisanego dla naszego panelu.
Code: c
Następnie podajemy adresy zmiennych jakie użyliśmy w panelu:
Code: c
W moim przypadku adresacja jest ciągła (co 2 bajty - wynika to ze specyfikacji pamięci zmiennych panelu), ale zrobiłem tak tylko i wyłącznie dla własnej wygody. Adresacja nie musi być ciągła.
Teraz możemu już przystąpić do wymiany danych z panelem. Służą do tego 2 funkcje, które należy umieścić w głównej pętli programu:
Code: c
Pierwsza z nich odpowiedzialna jest za przetworzenie odebranych z wyświetlacza danych. Zawiera w sobie mechanizm timeoutu na wypadek zaistnienia błędów w transmisji z wyświetlacza do systemu mikroprocesorowego.
Zadaniem drugiej jest zapisanie naszych zmiennych do panelu. Można by to wszystko zapisać razem w jednej funkcji, ale ze względu na specyficzne zastosowanie jakie miały u mnie ostatnio te funkcje postanowiłem, że będą one osobno. Obydwie funkcje pobierają jako argument wskaźnik na timer programowy (o timerach programowych możesz poczytać tutaj). Jak we wszystkich moich kodach, także i tutaj przyjęta została rozdzielczość timerów programowych wynosząca 10ms.
Jak widać powyżej potrzebujemy dwóch niezależnych timerów programowych.
Napisałem wcześniej, że uP wysyła do panelu jedynie te zmienne których wartość uległa zmianie od ostatniej wysyłki. Jest to jak najbardziej prawdą. Jednak funkcja ta ma pewną "furtkę" w postac przesłania o panelu pełnej listy zmiennych co określony czas. Wyobraźmy sobie sytuację,w której wyłączyliśmy zasilanie panelu bez wyłączania zasilanai systemu mikroprocesorowego. Nasz system wysyła sobie dane do panelu (a raczej nie wysyła jeżeli nie uległy zmianie). Jednak skąd u licha ma on wiedzieć, że panel został zrestartowany? Owszem można to rozwiązać odczytując statusy z rejestrów kontrolnych panelu. Jednak jest to dodatkowy nakład kodu, który moim zdaniem jest niepotrzebny. Wprowadziłem zatem prosty mechanizm, który cyklicznie co czas równy 255*CzasAktualizacjiZmiennychDGUS przesyła nam pełną listę zmiennych do panelu. Dzięki temu unikniemy sytuacji jaką opisałem powyżej.
A teraz dostęp do zmiennych:
- jako uint16_t
Code: c
- jako uint8_t
Code: c
- jako pojedyncze bity
Code: c
Przestrzegam aby pamiętać, że maksymalny indeks tablicy zmiennych jaki możemy wybrać to IloscZmiennychDGUS-1, w przeciwnym wypadku poślemy nasz program w wieczną otchłań... Należy o tym pamiętać tworząc dowolne pętle indeksujące tablicę zmiennych.
Zastanawiałem się również nad implementacją mechanizmu odczytu numeru aktualnie wyświetlanego ekranu. Jednak w toku pisania programu zrezygnowałem z takiej możliwości uznając ja za (przynajmniej dla mnie) całkowicie zbędną. Wynika to z faktu, że tworząc wizualizację dokładnie znamy numery poszczególnych plansz i chcąc wyświetlić jakąś na ekranie po prostu podajemy jawnie jej numer. Jeżeli już zaistniałaby konieczność wykonania akcji związanej z przejściem do konkretnej planszy to skupiłbym się raczej na użyciu w wizualizacji opcji przełączenia planszy z wysłaniem jakiegoś numeru który jej przyporządkowujemy. Dzięki temu nie trzeba będzie rozbudowywać kodu po stronie mikrokontrolera - wystarczy jedną z wirtualnych zmiennych wymiany danych przeznaczyć na przechowywanie właśnie tej wspomnianej wartości.
Przykładowy kod zawiera funkcję main w postaci:
Code: c
Jak widać wszystko jest jasne i przejrzyste. Patrząc na ciało funkcji main od razu wiemy co tak właściwie robimy w programie (bo zdarza się, że czasem sami tego nie wiemy...

Praca z pacjentem...
Na mojej stronie zamieściłem gotowy, sprawdzony, działający przykład użycia biblioteki, oraz prostą wizualizację współpracującą z tym przykładem. W katalogu PROJEKT_DGUS znajduje się przykładowy projekt dla panelu DGUS o przekątnej 4,3". Projekt można otworzyć do edycji przy pomocy DGUS_SDK dostępnego na www.whiteelectronics.pl lub też użyć już przygotowanej wizualizacji. W tym celu należy przygotować kartę microSD o pojemności NIE WIĘKSZEJ niż 2GB, sformatować ją w systemie plików Fat32 a następnie skopiować na nią cały katalog DWIN_SET. Po włożeniu karty do wyświetlacza powinien on samoczynnie załadować jej zawartość. Jeżeli to nie nastąpi to należy wyłączyć i włączyć zasilanie wyświetlacza. Po wczytaniu wizualizacji kartę można trwale usunąć ze slotu, inaczej przy każdym restarcie wizualizacja będzie na nowo wczytywana.
Istnieje również możliwość wgrywania wizualizacji i parametrów konfiguracyjnych do panelu bezpośrednio z poziomu środowiska DGUS_SDK - wtedy karta nie jest nam wcale potrzebna.
Cool? Ranking DIY