logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Czytamy notę katalogową i piszemy sterownik wyświetlacza 7-segmentowego LED CH455H w Arduino

p.kaczmarek2 22 Lip 2024 15:50 1143 1
  • Płytka Arduino podłączona do wyświetlacza LED z godziną 16:35
    Dzisiejszy projekt będzie opierać się o Arduino. Pokażę tutaj jak uruchomić kontroler wyświetlacza/klawiatury ze starego tunera sat w oparciu o jego notę katalogową oraz bibliotekę Wire z Arduino. Poznamy szczegóły jego interfejsu szeregowego opartego o linie SDA i SCL i spróbujemy przygotować podstawę zegara bądź wyświetlacza temperatury. Całość pokażę w praktyce, krok po kroku, chociaż jakaś podstawowa znajomość programowania i protokołów się przyda.

    Prezentowany tu układ zdobyłem za darmo ze starego tunera Wiwa HD90. Szczegóły tutaj:
    Stare tunery sat, Wiwa HD90, podwójny teardown, obudowa, części DIY za darmo?

    Wstępne rozpoznanie
    Pierwszym krokiem jest wyszukanie noty katalogowej. W tym przypadku udało mi się znaleźć angielskojęzyczną wersję:
    Schemat podłączenia układu CH455 z interfejsami sygnałowymi
    Są tutaj tylko dwie linie do komunikacji. Jest obiecująco. Jest jeszcze sygnał przerwania (pewnie od klawiatury), ale to nie jest konieczne na początek. Patrzymy dalej:
    Tabela funkcji kontrolera wyświetlacza i klawiatury z noty katalogowej.
    Komunikacja kompatybilna z I2C, nieźle! Zaraz sprawdzimy szczegóły.

    Schemat podłączenia
    Schematów połączenia jest kilka, oto najbardziej podstawowy (8 segmentów, wyświetlacz z wspólną katodą):
    Schemat układu połączeń dla kontrolera z wyświetlaczem 7-segmentowym.
    Dzięki dodaniu kilku tranzystorów też i wyświetlacze o wspólnej anodzie wysteruje:
    Schemat podłączenia wyświetlacza LED z układem CH455G
    ... ale my mamy całe PCB gotowe, wystarczy wlutować się w oznaczone punkty na płytce: 3.3V, GND, SCL i SDA:
    Zbliżenie na podłączenie kabli w projekcie Arduino
    Całość:
    Płyta główna tunera satelitarnego połączona z Arduino z wyświetlaczem LED.

    Interfejs szeregowy
    Poniższa sekcja noty katalogowej może wyglądać strasznie, ale na szczęście to wszystko jest mniej więcej standaryzowane, tak jak zresztą napisali na początku, "compatible with I2C". Komunikacja tam podzielona jest na transakcje, każda wysyła daną ilość bajtów, poprzedzona jest warunkiem start i zakończona warunkiem stop.
    Schemat interfejsu szeregowego CH455 z noty katalogowej
    W tym konkretnym przypadku transakcja ma sześć kroków: sygnał start, pierwszy bajt, pierwsze acknowledge, drugi bajt, acknowledge dwa, oraz stop. Czyli nie można tu wysłać więcej niż dwóch bajtów...
    Dodatkowo nie widzę tu adresacji urządzeń. Pierwszy bajt to rejestr, a drugi to wartości do wpisania. Ten sam schemat występuje i dla konfiguracji wyświetlacza (jeden rejestr) i dla wyświetlania cyfr (cztery rejestry, po jednym na cyfrę).

    Skaner I2C
    Zasadniczo ten protokół nie jest zgodny z I2C, bo nie ma adresacji urządzenia, ale skaner I2C z dokumentacji Arduino też powinien coś wykryć. Odpowiadać powinny adresy, pod którymi jest kontrola wyświetlacza oraz wartości segmentów. To pozwoli nam sprawdzić, czy poprawnie podłączyliśmy SDA i SCL.
    Na Arduino UNO to piny A4(SDA) i A5(SCL).
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Wyświetlacz odpowiada - pora pójść o krok dalej.
    Zrzut ekranu z wynikami skanowania I2C na Arduino
    Zweryfikujmy te adresy z notą. Tutaj są przesunięte, bo Wire wysyła adres urządzenia z dopisanym bitem R/W po prawej stronie. A więc, 0x24 razy dwa to 0x48. Hm, to by się zgadzało z notą:

    Fragment dokumentacji kontrolera dla parametru systemowego

    Pierwsze segmenty
    Teraz wracamy znów do noty katalogowej. Pierwsze co trzeba ruszyć to rejestr kontrolny. Tutaj jednak trzeba pamiętać, że funkcja Wire.beginTransmission bierze za argument adres urządzenia I2C, który jest tutaj 7-bitowy, a na magistralę wysyła go po przesunięciu o jeden bit, dopisując najmłodszy bit, czyli read/write. Szczegóły:
    https://www.arduino.cc/reference/en/language/functions/communication/wire/
    Nasze urządzenie nie ma tej adresacji, więc stosujemy mały trik - podzielimy na 2 adres rejestru do którego chcemy się dostać. Jest to równoznaczne z przesunięciem go o 1 bit w prawo.
    Fragment dokumentacji CH455 dotyczący komend systemowych wyświetlacza.
    Fragment dokumentacji technicznej kontrolera wyświetlacza CH455
    A więc mamy format komendy najpierw 0x48, a potem bitowo 0[INTENS][7SEG][SLEEP]0[ENA].
    Intensity (poziom jasności) jest 3 bitowy.
    A więc tak, ustawiamy:
    - intens na największą
    - 7seg tryb na włączony (tak nastawiłem na początku, potem to poprawiałem...
    - sleep na wyłączony
    - enabled na włączony
    Wpisujemy bity:
    0[111][1][0]0[1]B
    Czyli zasadniczo mamy:
    01111001b binarnie a w hex 0x79.
    Otwieramy dokumentację Wire:
    https://www.arduino.cc/reference/en/language/functions/communication/wire/
    Wpisujemy w kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Myślałem, że jeszcze będę musiał coś wpisać w rejestry od cyfr, ale nie - pierwsze LEDy już zaświeciły. Coś działa:
    Wyświetlacz segmentowy z działającymi cyframi na płytce drukowanej.


    Rejestry cyfr
    Teraz patrzymy jak zapalić segmenty. Jest o tym nieco informacji w nocie katalogowej:
    Sekcja 6.2 z dokumentacji - komenda ładowania danych słowa
    Wpisujemy adres rejestru w kod i wysyłamy do niego 0xff, wszystkie bity zapalone. Oczekujemy wyświetlenia ósemki.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Działa!:
    Wyświetlacz 7-segmentowy z cyframi 8.8.8.8


    Autoinkrementacja adresu?
    W poprzednich kontrolerach była wspierana autoinkrementacja adresu, czyli mogłem podać adres rejestru a potem wpisać na kolejne komórki pamięci kilka bajtów. Tutaj wedle noty katalogowej tak nie można, ale czy na pewno?
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Nie działa. Trzeba osobno adresować. Nie ma tu raczej zaskoczenia, w nocie katalogowej widziałem wzmianki o tym, że wysyłamy dwa bajty na raz...


    Wszystkie cyfry
    Pora już zrobić funkcję pomocniczą która reprezentować będzie jedną transakcje, czyli wpisanie bajtu na dany adresy:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    W oparciu o to uruchamiam wyświetlacz i wysyłam cztery ósemki:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Działa. Mamy cztery ósemki:
    Elektroniczny wyświetlacz z liczbą
    Dla pewności zrobiłem odliczanie:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Prawie działa, chociaż mam wrażenie, że jeden segment cały czas się świeci...
    Wyświetlacz 7-segmentowy pokazujący zegar 88:88
    Następnie kolejno wgrywałem programy wysyłające kolejne potęgi dwójki (1, 2, 4, 8, 16, 32, 64, 128) aby zbadać, który segment to który.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Wpisuję kolejno potęgi dwójki, patrzę co się zapala, patrzę na nazewnictwo z Wikipedii (segmenty określone są literami) i spisuję do kodu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Udało się tak uzupełnić wszystkie segmenty, oprócz jednego...

    Poprawiam swoje błędy
    W trakcie wypisywania segmentów zorientowałem się, że ciągle świeci mi się segment E. Szybka weryfikacja płytki pokazała, że nie jest to zwarcie. Winna okazała się niepoprawna inicjalizacja wyświetlacza - u mnie on pracuje w trybie 8 segmentów, więc bit "7seg" powinien być zgaszony:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Wraz z tą zmianą zapalanie segmentów zaczęło przebiegać w pełni poprawnie.


    Łączenie segmentów w znaki
    Mamy już segmenty. Teraz trzeba utworzyć cyfry (i ewentualnie kilka liter), ale... to już było szczegółowo omawiane w moim temacie o PIC18F2550:
    Tutorial PIC18F2550 + SDCC - Część 5 - Wyświetlacz 7-segmentowy i przerwania
    Więc, powtarzając ten proces, miałem już gotowe segmenty:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Potem wprowadziłem znaki do tablicy. Operatorem | łączę tutaj poszczególne bity w całość. Zerowe miejsce na tablicy odpowiada znakowi 0, pierwsze miejsce znakowi 1, itd.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Dzięki temu łatwo jest indeksować tę tablicę wartościami liczbowymi by dostać się do kodów znaków.
    Oto testowe odliczanie:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Wszystko działa:





    Kolejność znaków
    Mamy cztery rejestry - czy odpowiadają one kolejnym znakom?
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Rezultat:
    Wyświetlacz siedmiosegmentowy z cyframi 4321
    Kolejność znaków jest odwrócona.


    A ósmy segment?
    W trakcie wypisywania segmentów pominąłem jedną z potęg dwójki - 32. Za co ona odpowiada?
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Eksperymentalnie określiłem, że jest to dwukropek w przypadku rejestru 0x6C. Dla pozostałych rejestrów nic nie jest zapalane.
    Wyświetlacz LED 7-segmentowy z podwójnym dwukropkiem


    Łączymy wszystko w całość
    Załóżmy, że robimy zegar i odliczamy osobno minuty i godziny. Musimy jakoś rozbić minuty i godziny na osobne cyfry i włożyć je w odpowiednie rejestry w pamięci. Przyda nam się do tego operator dzielenia całkowitego (na integerach), nim wyłuskamy ilość dziesiątek, oraz operator modulo (reszta z dzielenia całkowitego), by wyłuskać jedności:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Do rejestru 0x6C dopisuję bit od dwukropka.
    No i jeszcze jakieś przykładowe wywołanie (to nie odlicza poprawnie czasu, to tylko demonstracja):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Działa:




    Odczyt klawiszy
    Zaglądamy do noty katalogowej:
    Instrukcja dotycząca odczytu kodu naciśnięcia klawisza.
    Tym razem najmłodszy bit z adresu jest zapalony. To by się zgadzało z adresacją 7-bitową gdzie doklejany bit R/W w przypadku operacji read jest 1. A więc piszemy pomocniczą funkcję:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Wywołujemy ją dla naszego rejestru (przy dzieleniu na 2 adresu jedynka się zgubi, ale requestFrom potem ten bit i tak dopisze zapalony bo operacja to odczyt):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Testujemy i wciskamy osobne przyciski:
    Wyświetlenie logów na temat adresów I2C
    Trzeba jeszcze te wartości zinterpretować:
    Tabela ze schematem kodów klawiszy i adresami segmentów dla wyświetlacza LED
    Czyli bit 0x40 mówi nam czy klawisz jest w tym momencie wciśnięty a pozostałe bity to zasadniczo indeks klawisza (a dokładniej indeksy wiersza i kolumny). Nie ma tu wsparcia wciśnięcia kilku klawiszy na raz. A więc, wyodrębnijmy w kodzie informacje o wciśnięciu oraz indeks klawisza:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Bardzo ładnie widać tu jak trzymałem klawisz o kodzie 7 a potem go zwolniłem:
    Zrzut danych z szeregowej komunikacji Arduino

    Podsumowanie
    Wyświetlacz udało się uruchomić, chociaż nie obyło się bez pomyłki (źle oceniłem, że bit 7seg powinien być 1, a powinien być 0, gdyż tu ósmym segmentem jest dwukropek). Dodatkowo okazało się, że kropki nie są nigdzie podłączone, więc w tej formie temperatury nie wyświetlimy. Można by spróbować rozważyć jakąś modyfikację, nie wiem, może przełączyć kropki pod dwukropek a dwukropek odpiąć lub do MCU podłączyć do wolnego GPIO, musiałbym sprawdzić dokładniej PCB.
    Jaki z tej zabawy wniosek? To raczej pozostawiam wam, chociaż ja bym żartobliwie dodał, że jak się umie czytać noty katalogowe, to prawie każde urządzenie staje się "modułem z chin do uruchomienia z Arduino".

    Fajne? Ranking DIY
    Pomogłem? Kup mi kawę.
    O autorze
    p.kaczmarek2
    Moderator Smart Home
    Offline 
  • #2 21166030
    keseszel
    Poziom 26  
    Na takie coś czekałem w Twoim wykonaniu.
REKLAMA