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:

//Funkcja obsłgi danych odebranych z panelu
void DGUS_UART_RX_STR_EVENT(uint8_t *tim);
//Funkcja wysyłania danych do panelu.
void DGUS_UART_DATA_TRANSMIT_EVENT(uint8_t *tim);
//Funkcja pozwala na wyswietlenie konkretnego okna
void DGUS_DisplayWindow(uint16_t window);
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":
typedef union{
 struct{
 uint16_t Adr16;
 uint8_t NoW;
 uint16_t Val16;
 };
 struct
 {
 uint8_t Adr8Lo;
 uint8_t Adr8Hi;
 uint8_t NoW;
 uint8_t Val8Lo;
 uint8_t Val8Hi;
 };
struct
{
 uint16_t Adr16;
 uint8_t NoW;
 struct {
 unsigned int b0 : 1;
 unsigned int b1 : 1;
 unsigned int b2 : 1;
 unsigned int b3 : 1;
 unsigned int b4 : 1;
 unsigned int b5 : 1;
 unsigned int b6 : 1;
 unsigned int b7 : 1;
 unsigned int b8 : 1;
 unsigned int b9 : 1;
 unsigned int b10 : 1;
 unsigned int b11 : 1;
 unsigned int b12 : 1;
 unsigned int b13 : 1;
 unsigned int b14 : 1;
 unsigned int b15 : 1;
 };
};
 uint8_t Tab8[5];
}Transceive;
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:

//------------------------------------------------
// Konfiguracja wymiany zmiennych z panelem
#define IloscZmiennychDGUS 20 //ilosć zmiennych jakimi wymieniać się będziemy z panelem
#define CzasAktualizacjiZmiennychDGUS 25 //*10ms
//------------------------------------------------
//Konfiguracja UART
#define UART_no 2 //numer UART: 0, 1 (dla procków z dwoma UARTami) lub 2 dla pozostałych procków
#define UART_DGUS_BAUD 57600
#define UART_DGUS_TX_BUF_SIZE 16 //rozmiar bufora nadawczego
// definicje na potrzeby RS485
//------------------------------------------------
#define RS485act 0 //1 - RS485 aktywny, 0 - nieaktywny
#if RS485act==1
#define UART_DGUS_DE_PORT PORTB
#define UART_DGUS_DE_DIR DDRB
#define UART_DGUS_DE_BIT (1<<PB2)
#endif

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.

USART_DGUS_Init();

Następnie podajemy adresy zmiennych jakie użyliśmy w panelu:
ZmienneDGUS[0].Adr16=0x0010;
ZmienneDGUS[1].Adr16=0x0012;
ZmienneDGUS[2].Adr16=0x0014;
ZmienneDGUS[3].Adr16=0x0016;
ZmienneDGUS[4].Adr16=0x0018;
ZmienneDGUS[5].Adr16=0x0020;
ZmienneDGUS[6].Adr16=0x0022;
ZmienneDGUS[7].Adr16=0x0024;
ZmienneDGUS[8].Adr16=0x0026;
ZmienneDGUS[9].Adr16=0x0028;
ZmienneDGUS[10].Adr16=0x0030;
ZmienneDGUS[11].Adr16=0x0032;
ZmienneDGUS[12].Adr16=0x0034;
ZmienneDGUS[13].Adr16=0x0036;
ZmienneDGUS[14].Adr16=0x0038;
ZmienneDGUS[15].Adr16=0x0040;
ZmienneDGUS[16].Adr16=0x0042;
ZmienneDGUS[17].Adr16=0x0044;
ZmienneDGUS[18].Adr16=0x0046;
ZmienneDGUS[19].Adr16=0x0048;
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:

DGUS_UART_RX_STR_EVENT(&L_TimeoutDGUS);
DGUS_UART_DATA_TRANSMIT_EVENT(&L_OdswiezaniePanelu);
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żnaby 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. 

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

ZmienneDGUS[6].Val16=67;

- jako uint8_t
ZmienneDGUS[2].Val8Hi=15;
 ZmienneDGUS[2].Val8Lo=99;

- jako pojedyncze bity
ZmienneDGUS[0].b0=true;
ZmienneDGUS[3].b4=true;
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:

int main(void)
{
initPeripherals();//inicjalizujemy nasz układ do pracy
 
bLCDxy(0,1);
bLCDpgmtext(PrzedstawSie1);
bLCDxy(0,2);
bLCDpgmtext(PrzedstawSie2);
LCDdisplay(Freeze); //Wysyłamy bufor obrazu do wywietlacza
waitsek(2);
 
/*
 * Tutaj konfigurujemy adresy jakie nadalismy zmiennym w DGUS_SDK
 */
ZmienneDGUS[0].Adr16=0x0010;
ZmienneDGUS[1].Adr16=0x0012;
ZmienneDGUS[2].Adr16=0x0014;
ZmienneDGUS[3].Adr16=0x0016;
ZmienneDGUS[4].Adr16=0x0018;
 
ZmienneDGUS[5].Adr16=0x0020;
ZmienneDGUS[6].Adr16=0x0022;
ZmienneDGUS[7].Adr16=0x0024;
ZmienneDGUS[8].Adr16=0x0026;
ZmienneDGUS[9].Adr16=0x0028;
 
ZmienneDGUS[10].Adr16=0x0030;
ZmienneDGUS[11].Adr16=0x0032;
ZmienneDGUS[12].Adr16=0x0034;
ZmienneDGUS[13].Adr16=0x0036;
ZmienneDGUS[14].Adr16=0x0038;
 
ZmienneDGUS[15].Adr16=0x0040;
ZmienneDGUS[16].Adr16=0x0042;
ZmienneDGUS[17].Adr16=0x0044;
ZmienneDGUS[18].Adr16=0x0046;
ZmienneDGUS[19].Adr16=0x0048;
 
while(1)
{
 wdt_reset(); //reset układu watchdog
 SysTick(); //obsługa timerów programowych
 DGUS_UART_RX_STR_EVENT(&L_TimeoutDGUS);
 wyswietlanieNaLCD(); //tu wrzucamy do bufora obrazu dane dla LCD 2x16
 wariacjaZmiennych(); //tu robimy sobie testowe wymuszenie zmian wartosci zmiennych
 przelaczanieEkranow(); //tu przy pomocy timera programowego skaczemy po ekranach DGUS
 DGUS_UART_DATA_TRANSMIT_EVENT(&L_OdswiezaniePanelu);
 LCDdisplay(Clear); //Wysyłamy bufor obrazu do wywietlacza
}
}

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...
Poniżej 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.

 Przed korzystaniem z przykładu zapoznaj się z plikiem CzytajToKodyAVR.

Do pobrania:

Użyj opcji uploadu plików, aby przekazać mi kod do sprawdzenia. Postaram się zajrzeć do niego tak szybko jak będzie to możliwe. Paczkę z poprawionym kodem umieszczę w tym samym miejscu.

 

 

Jeżeli wystąpi sytuacja, w której zostanie wyświetlona zawartość folderu z innego działu - należy wyczyścić cache przeglądarki! Następnie przeładować stronę.


Komentarze  

 
# ST WebSite - Biblioteka obsługi paneli operatorskich DGUS dla AVRsamomoto.pl 2016-12-07 20:47
Wreszcie ktoś pisze na temat, a nie próbuje i w efekcie się błąka nie wiadomo
gdzie. Poproszę o więcej
Odpowiedz | Odpowiedz z cytatem | Cytować
 

Licznik odwiedzin

Mapa odwiedzin



 

Copyright © ST WebSite 2017

Stronę hostuje FutureHost. []

Strona korzysta z plików cookie. Dane przechowywane na Twoim komputerze służą wyłą…cznie do poprawienia funkcjonalnoś›ci witryny. Jeżeli tego nie akceptujesz - powinieneś› ją… opuś›cić‡.

Akceptujesz ciasteczka z tej witryny?