
Wiele osób zastanawiało się dlaczego kolorowe graficzne wyświetlacze działają bardzo wolno z Arduino UNO/Mega i wszystkimi AVR Mega/Tiny. Przeprowadziłem testy porównawcze wyświetlacza 128x160 ze sterownikiem IL9306 pracującym z interfejsem SPI. Do testów posłużyło Arduino UNO i KA-NUCLEO-F411CE.

Zainstalowałem bibliotekę „TFT_ILI9163C-master” ze strony „Nettigo”. Uruchomiłem przykład „Cube”, efekty widać na filmie.
Animacją bym tego nie nazwał. Program nie robi nic innego jak animowanie sześcianu (przerwania od timera działają), widać migotanie ekranu (komenda CLS). Wszystko to wynika z faktu, że kasowanie ekranu trwa 237ms, rysowanie sześcianu 40..47ms co daje 3..4 klatki na sekundę.
Czy da się po poprawić? Nie za bardzo! Można taktować uC 20MHz a nie 16, ale szału nie będzie.
Często (najczęściej) biblioteki napisane są żałośnie i choć sterownik wyświetlacza ma funkcje rysowania linii, prostokątów czy okręgów to biblioteka ich nie wykorzystuje. Funkcje te pozwalają szybko czyścic ekran (kilkanaście bajtów zamiast kilkudziesięciu tysięcy) rysować linie itp. Podobnie źle są pisane funkcje umieszczania tekstów, zamiast zdefiniować okno wysyłać tylko dane, stawiany jest punkt po punkcie co spowalnia umieszczanie tekstu kilka, kilkanaście razy. Niestety, w przypadku IL9306 i rysowania sześcianu praktycznie nic nie da się zrobić.
Zagoniłem do pracy ARM STM32F411CE. Zegar ustawiłem na 60MHz, co pozwoliło taktować SPI częstotliwością 15MHz, maksymalną dopuszczalną dla IL9306. Przeniosłem bibliotekę z Arduino, oto efekt:
Słaby coś ten ARM, animacja niewiele szybsza (użyłem HAL, gdyby wykorzystać dostęp rzez rejestry animacja byłaby prawie 2 razy szybsza niż na UNO). Nie, to nie ARM słaby tylko programista, który przeniósł kod nie wykorzystując możliwości sprzętowych ARM. Stworzyłem bufor na dane dla wyświetlacza (128*160*2=40960bajtów) i zagoniłem do pracy DMA. Efekt:
Tworzenie klatki animacji trwa ok 2,5ms, transmisja danych do LCD przez DMA poniżej 25ms. Używanie wyświetlacza ma sens! Menu nie rysuje się „godzinami” można wyświetlać animacje. 25ms daje 40 klatek na sekundę! W porównaniu do UNO z 3..4 klatkami to rakieta! Należy zauważyć, że gdy dane są wysyłane do LCD CPU może generować kolejną klatkę!
Dlaczego napisałem ten artykuł?
Wielu Arduinowców kusi się reklamami sklepów i kupuje wyświetlacze 320x240 czy nawet 640x480 do UNO czy MEGA. Nie oszukujmy się, bez DMA, szybkiego SPI czy interfejsu równoległego, używanie kolorowych wyświetlaczy bez akceleratora graficznego (np. FT8xx) o dużej rozdzielczości nie ma sensu! Owszem, jeśli będzie to np. termometr, miernik napięcia, gdzie wyświetlany jest jeden ekran, modyfikowana jego część i skorzystamy z okna wyświetlania, ma to sens. Gdy jednak zrobimy menu, przechodzenie pomiędzy poszczególnymi stronami będzie wyglądało żałośnie. O tle innym niż jedna barwa raczej należy zapomnieć.
Podstawowym problemów AVR-ów jest mała ilość RAM. Gdyby było jej więcej, operacje graficzne można by przeprowadzić na pamięci po czym wysłać cały bufor do wyświetlacza. Nie można skorzystać z mechanizmu przerwań, ponieważ wejście i wyjście z przerwania zajmie więcej czasu niż czekanie aż bufor nadawczy zostanie opróżniony. W takim przypadku, wysłanie całego bufora zajmie ok 41ms dla 16MHz i ok 33ms dla 20MHz (dane teoretyczne). Do tego należy dodać rysowanie grafiki, w tym przypadku max 47ms. Daje to czas ok 90ms czyli ponad 11 klatek na sekundę. Zaletą tego rozwiązania jest brak migotania ekranu, bo nie ma operacji jego kasowania.
Sytuację ratują Xmega, które nie dość, że mają więcej RAM niż Mega/tiny to są wyposażone w DMA. Niestety, porównanie cen Xmega z AVR wypada na niekorzyść Xmega. Jeśli jeszcze uwzględnimy ich wyposażenie w peryferia, ilość pamięci oraz fakt, że nadal są to CPU 8-bit, nie ma sensu się nimi zajmować.
Na koniec porównanie ARM z AVR, gdzie na AVR wyraźnie widać rysowanie tła podczas jego zmiany.
Próbowałem bardziej bajerancki efekt:
Mimo iż na UNO ustawiłem zmianę wielkości kwadratu tła nie o 1 po każdym wyświetleniu tylko o 10, nic to nie dało. Owszem, można by nie czyścić całego wyświetlacza tylko kilka fragmentów, ale trzeba się narobić a i tak będzie miga

Mam nadzieję, że teraz użytkownicy AVRmega/tiny ArduinoUNO/Mega i podobnych, dobrze zastanowią się zanim wykorzystają kolorowy wyświetlacz.
PS
Kody źródłowe dla Arduino i ARM w załączniku. Kody nie są doskonałe, np. strob CS może być zdejmowany zbyt szybko, co może powodować błędy na ostatnim pikselu. Celem kodów nie było napisanie doskonałych funkcji komunikacji z wyświetlaczem ale pokazanie różnicy pomiędzy uC z wystarczającą ilością pamięci RAM i DMA oraz bez tych udogodnień (UNO z 2kB RAM).
Cool? Ranking DIY