Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C

p.kaczmarek2 03 Mar 2023 09:30 1689 6
Computer Controls
  • Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Witajcie, zapraszam na relację z konstrukcji zegara na PIC18F2550 napisaną w formie tutoriala, wszystko krok po kroku. Pokażę tu jak i z czego tworzyłem prosty projekt DIY na prośbę jednego z czytelników. Wykorzystamy tu wyświetlacze 7-segmentowe, rejestr przesuwny, obsłużymy przyciski a może nawet potem z I2C coś ruszymy. Nie będzie to kompletny opis i pewnie będzie kontynuowany w dalszym temacie, więc proszę nie oczekiwać pełnoprawnego produktu na końcu postu.
    Docelowo zegar będzie mieć nawet zaprojektowaną pod niego płytkę, będzie pokazywać czas i datę, wykonywać pomiary temperatura i wilgotności i też będzie w stanie oferować kontrolę przekaźnikami, ale to wszystko dopiero za jakiś czas.

    Powiązane tematy samouczkowe
    Wiele konceptów stąd było omawianych już wcześniej, w związku z czym szczegółowość tłumaczenia tutaj będzie już nieco mniejsza. Zamiast tego po prostu zalinkuję tutaj wcześniejszejsze moje materiały na powiązane tematy:
    Tutorial podzielony jest na osobne tematy i tutaj znajdują się do nich linki.
    PIC18F SDCC tutorial cz. 1 - Konfiguracja środowiska pracy
    https://www.elektroda.pl/rtvforum/viewtopic.php?p=18304424#18304424
    PIC18F SDCC tutorial cz. 2 - Blink LED, piny IO, cyfrowe wejścia i wyjścia
    https://www.elektroda.pl/rtvforum/viewtopic.php?p=18389188#18389188
    PIC18F SDCC tutorial cz. 3 - Ustawienia oscylatora. Oscylator wewnętrzny, zewnętrzny, rezonator kwarcowy, PLL
    https://www.elektroda.pl/rtvforum/topic3657704.html
    PIC18F SDCC tutorial cz. 4 - Timery, przerwania
    https://www.elektroda.pl/rtvforum/viewtopic.php?p=18580858#18580858
    PIC18F SDCC tutorial cz. 5 - Obsługa wyświetlacza siedmiosegmentowego
    https://www.elektroda.pl/rtvforum/viewtopic.php?p=18580877#18580877
    PIC18F SDCC tutorial cz. 6 - Sterownik wyświetlacza LED MM5450
    https://www.elektroda.pl/rtvforum/topic3845301.html
    Poboczne powiązane tematy:
    Wyświetlacz 7 segmentowy tunera, uruchomienie z Arduino, rejestr przesuwny

    Uwaga organizacyjna i podziękowania
    Temat powstał na bezpośrednią prośbę i zainteresowanie jednego z czytelników, który również ma swój wkład w rozwój tego mini-projektu, a nawet wysłał mi do niego nieco wybranych przez siebie części:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    W związku z tym projekt jest taki a nie inny. Za wysłanie mi części bardzo dziękuję! Projekt będzie prowadzony dalej też i rozwijany wedle uwag czytelnika.

    Użyte środowisko i MCU
    Tak jak w tytule tematu - PIC18F2550 będzie sercem układu. Natomiast jeśli chodzi o środowisko, to początkowo pisałem na SDCC, ale potem by oszczędzić czasu przeniosłem się na MikroC, gdyż tam miałem gotowe funkcje do I2C. Nie wykluczam, że do SDCC potem wrócę, zwłaszcza, że preferuję te bardziej otwarte rozwiązania.
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C

    Krok 1: Minimalny układ
    Minęło trochę czasu, więc robimy twardy reset - zaczynam całkiem na nowo, oto minimalny układ z PIC18F na płytce stykowej.
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Zasilaczyk do płytki stykowej też jest tu przydatny, bo normalnie brzegowe linie masa/zasilanie nie są połączone, a on je tutaj łączy i też w razie czego pozwala zasilić projekt z zasilacza.
    Na początku też należy sprawdzić czy wszystko gra i czy blink LED działa:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Typowym błędem jest wgrywanie wsadu na z jakiegoś powodu martwy/niestartujący mikrokontroler bądź wgrywanie złego wsadu (starego, ze złego folderu, itd), więc warto sprawdzić, czy w ogóle nasz program się odpala i miga tak jak chcemy.


    Krok 2: Rejestr przesuwny
    Wyświetlacz już omawialiśmy, ale wtedy zajęliśmy cały jeden port 8-bitowy (8 pinów, czy tam 7, nie licząc kropki) by nim sterować. Spróbujmy zredukować ilość pinów - użyjemy do tego rejestru przesuwnego, czyli konwertera serial-in na paralel-out, wejście szeregowo (jedna linia danych i zegar), a wyjście równoległe (tutaj 8 pinów).
    Układ taki można kupić, ale by urozmaicić zabawę użyłem takiego z elektrośmieci. Wylutowałem go z PCB metodą topnik + spoiwo Pb, po prostu naniosłem topnik a potem spoiwo na jego wszystkie nóżki a potem je równomiernie podgrzałem grotem. Tak podgrzane luty pozwalają układowi wypaść z PCB, działa to dość dobrze o ile jego nóżki nie są zagięte a samo PCB jest jeszcze z czasów gdy nie panowało spoiwo bezołowiowe:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2CBudujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Rejestr uwolniony!
    Tak oto zyskujemy 74HCT164:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Oczywiście można kupić inny rejestr przesuwny, zresztą i tak są one dość tanie.
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    A jak nim sterować? To już pokazywałem w kontekście Arduino:
    Wyświetlacz 7 segmentowy tunera, uruchomienie z Arduino, rejestr przesuwny
    Pin MR resetuje cały układ - gdy ustawimy go w stan niski, to on zeruje wszystkie wyjścia. Piny DSA i DSB stanowią wejścia, na wejście rejestru wchodzi wynik iloczynu logicznego (AND) wartości na tych pinach. Na wejście rejestru informacja pobierana jest gdy sygnał zegara przechodzi ze stanu niskiego na wysoki (tzw. zbocze rosnące).
    Wystarczy krótka funkcja:
    Code: c
    Log in, to see the code

    Zakomentowana linijka z HC_DATA pozwala określić kolejność przekazywania bajtów - od najmłodszego, czy od najstarszego?
    Oczywiście piny trzeba ustawić, zdefiniować HC_DATA i tak dalej, jak również ustawić je w tryb wyjść.
    Oto cały kod przykładu, wraz z główną pętlą gdzie na rejestr przekazywane są kolejne liczby:
    Code: c
    Log in, to see the code

    W celu demonstracji użyłem płytki SYB170 z diodami LED:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Wykonałem połączenia - HC_CLOCK, HC_DATA, HC_RESET na odpowiednie wejścia rejestru. Dodatkowo też zasilanie, wiadomo, oraz na wyjścia rejestru LEDy.
    W ten sposób powstało prymitywne odliczanie binarne:



    I tutaj pojawia się pierwszy problem - czemu wszystko tak miga? Czyżby był błąd?
    Niestety nie ma tutaj błędu - użyty rejestr przesuwny ma taką prostą konstrukcję, że kolejno przesuwa wyjścia co może być widoczne dla człowieka. Można by użyć droższego rejestru, takiego z kontrolą latch (przerzucenia w jednym momencie nowych danych na wyjścia), ale my sobie poradzimy i bez tego - niedługo pokażę jak.


    Krok 3: Wyświetlacz - jedna cyfra
    Czytelnik wysłał mi te piękne, niebieskie wyświetlacze, która zdają się być nawet nieco większe od wyświetlaczy które posiadam ze sprzętów z elektrośmieci i dają fajny, przyjemny odcień światła:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Jest to model 5261AB, wyświetlacz ze wspólną katodą, dwucyfrowy.
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Wymiary i pinout:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    No i cena:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Jakieś 25 zł za 10 sztuk... 2.5zł za sztukę.
    Warto zajrzeć też do jego parametrów - mamy tu parametry potrzebne do określenia jaki rezystor jest potrzebny, Vf, prąd segmentu... tak jak dla zwykłej diody LED:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Ciekawe, że producent również określa, że przy 1/10 wypełnienia przy 10kHz można puszczać do 100mA przez segment. To się może nam przydać, gorzej, jeśli dobierzemy taki rezystor a potem nasz multipleksing się popsuje i wyświetlacz dostanie ciągły prąd 100mA...
    Ostatecznie zdecydowałem się na te 30mA prądu ciągłego i uruchomiłem wyświetlacz pojedynczo. Tak jak w poprzednim temacie (część o wyświetlaczu), ale zamiast zapisywać segmenty danego znaku do portu B:
    Code: c
    Log in, to see the code

    wysyłam je do rejestru przesuwnego:
    Code: c
    Log in, to see the code

    Oto cały kod:
    Code: c
    Log in, to see the code

    Rezultat:



    Każda z cyfr ma osobno wszystkie piny od segmentów. To trochę mi skomplikowało sprawę. Wiadomo, że wspólne anody (czy tam katody) powinny być osobno by sterować osobno każdą z cyfr, ale segmenty... no cóż, troszkę musiałem popodłączać na płytce by obie cyfry uruchomić:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C


    Krok 4: Wyświetlacz - multipleksing
    Pora powitać tranzystory - tutaj dwa, po jednym na cyfrę. Oczywiście wraz z rezystorami ograniczającymi prąd bazy, tak jak w poprzedniej części o wyświetlaczu. Użyłem tutaj BC547, NPN, oczywiście wspólna katoda do kolektora a emiter tranzystora do masy. Odpowiednio zmodyfikowałem kod, na razie bez przerwań.
    Code: c
    Log in, to see the code

    Kod odlicza i bardzo szybko (niezauważalnie dla ludzkiego oka) wyświetla na przemian obie cyfry. Dodatkowo tutaj jest wspomniane wcześniej rozwiązanie problemu z rejestr przesuwnym - przed shiftOut wyłączam oba tranzystory, by nie było tego krótkiego momentu gdzie świecą się losowe segmenty.
    Tyle, że powyższy kod robi wszystko w main i blokuje wszystkie inne czynności funkcją delay1ktcy. Pora użyć timera i przerwania, po prostu zwolnymi sobie main a funkcja przerwania będzie wywoływana co dany czas poprzez timer.
    Mamy do tego nawet wygodne narzędzie - MikroC Timer Calculator:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Poniżej mamy zasadniczo to samo, ale już z przerwaniem i timerem:
    Code: c
    Log in, to see the code

    Tak jak w temacie o przerwaniach. Rezultat:




    Krok 5: Wyświetlacz - lutujemy...
    Tutaj niestety przychodzi taki moment, że trzeba pożegnać się z płytką stykową i użyć wygodniejszego rozwiązania - łączenie wspólnych segmentów dla wielu cyfr byłoby tam już naprawdę problematyczne. Nie chciałem jeszcze projektować pod wyświetlacz PCB, więc zdecydowałem się na dość czasochłonną, ale skuteczną metodę dostępną dla każdego - wiercone płytki prototypowe, tutaj z osobnymi polami miedzi (każde jest osobno, dopiero musimy utworzyć nasze ścieżki):
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Takie płytki są naprawdę bardzo tanie, ale lutowanie na nich zajmuje dużo czasu:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    No i trzeba uważać, by nie przegrzewać ich padów, tam każdy pad lutowniczy jest osobno i nie ma dużej pojemności cieplnej, jak początkujący go przypali przesadnie rozgrzanym grotem to ten pad odpadnie.
    Wstępne przymiarki:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Zworki łączące segmenty obu cyfr:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Lutowanie na spodzie:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Drugi wyświetlacz:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Gotowe:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Niestety na spodzie też musiałem łączyć i sztukować:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Uprzedzając pytanie - dwukropki powstaną poprzez dodatkowe diody LED... po prostu takie wyświetlacze dostałem.
    Dużo było zabawy z tym lutowaniem.
    Kod został wzbogacony o obsługę dwóch dodatkowych cyfr.
    Code: c
    Log in, to see the code

    Efekt:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C




    Krok 6: Odmierzanie czasu
    Mniej więcej na tym etapie podpiąłem timer do odmierzenia czasu. Użyłem timera pierwszego, bo zerowy był już zajęty przez odświeżanie wyświetlacza. Do obliczenia wartości przepełnienia użyłem mikroC timer calculator. Tyle, że timer 1 nie był w stanie wywoływać przerwania co 1s, więc wybrałem okres 250ms:
    Code: c
    Log in, to see the code

    Na ten moment zdecydowałem się zliczać osobno sekundy, minuty i godziny. Możliwe, że potem wrócę do zliczania pełnej ilości sekund zamiast tak dzielić, ale w ten sposób było mi wygodniej. W przerwaniu timer1 zliczam wywołania do 4 a potem ustawiam kolejną sekundę:
    Code: c
    Log in, to see the code

    A oto funkcja wyświetlania tego (dba o to, by zawsze pozycje odpowiednich cyfr godziny/minuty/sekundy były niezmienne):
    Code: c
    Log in, to see the code

    Powyższa funkcja zakłada już 6 cyfr, ale w razie czego dwie ostatnie można po prostu zakomentować.


    Krok 7: Przyciski - część 1
    Teraz zobaczymy jak można ładnie wykorzystać istniejącą już konstrukcję układu aby dodać do niego przyciski bardzo "tanim kosztem", a dokładniej kosztem jednego wejścia mikrokontrolera. Tak, starczy tylko jedno IO - a będzie można było obsłużyć aż do 8 przycisków.
    Wystarczy podłączyć przyciski pomiędzy wybrany IO, a linie segmentów. Dodatkowo wybrany IO będzie mieć rezystor pull up (tutaj programowalny w PIC), by domyślnie ustawić stan wysoki. Następnie w procedurze skanowania przycisków będziemy kolejno wystawiać pojedynczy stan niski na kolejne przyciski (pozostałe bity) i badać czy ten stan niski "przeszedł" na pin wejścia.
    Jeśli "przejdzie", to znaczy, że dany przycisk jest wciśnięty. W przeciwnym razie, przycisk nie jest wciśnięty.
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Code: c
    Log in, to see the code

    Przerwanie ma teraz 5 kroków - 4 dla cyfr, a piąty dla skanu przycisków. Zmienna "cnt" reprezentuje stan przycisków, gdzie każdy bit odpowiada danemu przyciskowi. Kod można by umieścić w pętli, ale już nie chciałem komplikować - tu widać, że kolejno wystawiam stan niski na każdy kolejny pin rejestru i badan stan przyciski.
    Oto krótki test przycisków:



    Każdy przycisk odpowiada kolejnej potędze dwójki - jest dobrze, ale co się dzieje jak wciśniemy dwa przyciski na raz?
    Niestety wtedy system się psuje, wyświetlacz nawet nie wyświetla poprawnie.
    Bierze się to stąd, że zwierając dwa przyciski zwieramy wtedy też dwa wyjścia rejestru przesuwnego, więc uniemożliwiamy multipleksing fragmentów....

    Krok 8: Przyciski - część 2
    Trzeba naprawić problem z poprzedniego akapitu. Naprawa będzie w pełni sprzętowa. Po prostu musimy zablokować przyciski/wyjścia rejestru przesuwnego tak, by prąd mógł płynąć tylko w jedną stronę i nie mógł "zawrócić" - wystarczy dodać diody:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Tak włączone diody wciąż umożliwiają zwarcie danym przyciskiem naszego pojedynczego wejścia MCU do masy, ale jednocześnie uniemożliwiają zrobienie spięcia poprzez wciśnięcie kilku przycisków. Od teraz wciśnięcie na raz kilku przycisków daje poprawne rezultaty, np. jak wciśniemy przyciski pierwszy i trzeci to otrzymamy w rezultacie liczbę 5, czyli 2 do potęgi 0 dodać 2 do potęgi 2, czyli 1 + 4 = 5.





    Krok 9: Przyciski - część 3 - zdarzenia
    Teraz pora dodać proste programowane rozwiązanie problemu drgania styków oraz wprowadzić dwa przyciskowe zdarzenia - pierwsze wciśnięcie (wolna reakcja) oraz trzymanie przycisku (jak trzymamy dłużej niż dany okres czasu to zdarzenie się powtarza). Tak jak na komputerze - wciśnijcie dowolny klawisz, np. 'a' to zobaczycie, że klawisz pojawia się raz a potem się wielokrotnie powtarza.
    Na początku zdefiniujmy te tytułowe zdarzenia:
    Code: c
    Log in, to see the code

    Przy okazji zmienną określającą jak szybko powtórnie wyśle się zdarzenie hold.
    Code: c
    Log in, to see the code

    W celu dodania obsługi zdarzeń przetworzymy uzyskaną maskę przycisków.
    Może na początek poprawmy samo jej tworzenie - tak, by już była pętla:
    Code: c
    Log in, to see the code

    Wcześniej to było rozpisane osobno dla każdego i.
    Od razu lepiej. Teraz pytanie, co zrobić z tą zmienną newButtons?
    Oto przetwarzanie przycisków:
    Code: c
    Log in, to see the code

    Pamiętamy stary stan przycisków i w pętli porównujemy go z nowym. Jeśli nastąpi zmiana danego stanu przycisku, to resetujemy licznik tego przycisku. W przeciwnym razie go zwiększamy. Jak licznik osiągnie pierwszą ustalaną wartość (tutaj BUTTON_MIN_REPEATS) to wyzwalamy zdarzenie wciśnięcia - wciśnięcie pierwsze. Potem jeśli minie trochę czasu (dwa razy czas do pierwszego wciśnięcia) to co BUTTON_MIN_REPEATS jednostek czasu wyzwalamy kolejne zdarzenia, ale już oznaczone jako BUTTON_PRESS_HOLD.

    Analogicznie można by dodać też np. zdarzenie RELEASE (puszczenie przycisku), ale aż tak nie chciałem kombinować.

    Teraz przykład obsługi zdarzenia - wykorzystanie do edycji wartości sekund.
    Code: c
    Log in, to see the code

    Argument b to indeks przycisku, eventType to rodzaj zdarzenia. Na bazie rodzaju zdarzenia dobieramy co ile zmieniamy wartość (1 lub 10) i tą wartość dodajemy lub odejmujemy od sekund.
    Wszystko działa (chociaż chyba częstotliwość repeats można by zmniejszyć?):

    Krok 10: Wprowadzenie I2C
    Na tym etapie zdecydowałem się przejść na mikroC PRO for PIC, gdyż nie chciałem bawić się w uruchamianie od 0 I2C, jak jest przecież gotowa biblioteka i działa w darmowej wersji tego kompilatora.
    I2C wymaga rezystorów pull-up na liniach SDA i SCL. Na PIC18F2550 te linie to RB0 i RB1. Do testów użyłem termometru TC74.
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    TC74 używam zawsze na próbę ze względu na jego prostotę.
    Dokumentacja użytej biblioteki I2C znajduje się tutaj:
    https://download.mikroe.com/documents/compilers/mikroc/pic/help/i2c_library.htm
    Urządzenia I2C mają różne adresy, dzięki temu można na jednej magistrali podłączyć wiele urządzeń. MCU wywołuje najpierw adres urządzenia, a potem z nim się komunikuje. Z tego też powodu zabawę z I2C zaczynam zawsze od skanera:
    Code: c
    Log in, to see the code

    Powyższy kod podpiąłem do wyświetlacza by wiedzieć czy jakikolwiek adres się zgłasza - to pozwala sprawdzić, czy urządzenie I2C jest widziane.
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Pozwoli to też uniknąć błędów typu "kod komunikacji jest dobry, ale wpisany jest zły adres, więc nie otrzymujemy odpowiedzi".
    Sprawdźmy, czy adres jest ok. TC74A0...
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Te adresy są bez bitu R/W, więc go dopisałem jako 0. Zgadza się!
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Potem już (zgodnie z notą katalogową) podpiąłem odczyt temperatury z TC74:
    Code: c
    Log in, to see the code

    Weryfikacja działania (temperatura w pokoju + podgrzanie sensora latarką):
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C

    Krok 11: Piąta i szósta cyfra
    Bez zbędnego komentarza - dolutowałem kolejną parkę cyfr. Niestety brakło miejsca na ładne wyprowadzenie golpinów od baz tranzystorów, ale to tylko prototyp.
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C

    Krok 12: Edycja godziny/minuty/sekundy
    Jak na razie tylko na próbę - zobaczmy, jak zrobić prostą edycję.
    Po prostu damy kolejną zmienną określającą tryb pracy (zwykła praca, edycja godzin, minut, sekund)oraz kolejny przycisk, który pozwala przełączać pomiędzy kolejnymi trybami.
    Code: c
    Log in, to see the code

    Do zwiększania/zmniejszania wartości zmiennej użyłem preprocesora, pozwala to uniknąć nadmiernego pisania, a kompilator i tak nie widzi różnicy. Dodatkowo przy edytowanej parze cyfr podświetlam kropkę poprzez dotFlags, gdzie zapalony bit na danej pozycji odpowiada zapalonej kropce na danej pozycji.


    Krok 13: Czujnik temperatury i ciśnienia BMP280
    W zestawie od czytelnika dostałem też czujnik BMP280. Wiem, że dopiero co uruchomiłem prymitywny termometr TC74, ale myślę, że BMP280 też warto odpalić.
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Co to za czujnik?
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Ile kosztuje taka zabawa?
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Przyznam, że moim zdaniem jest dość tani. Zacząłem znów od skanu I2C (pozwala to uniknąć problemów z posiadaniem złego adresu urządzenia):
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Potem podjąłem najpierw próbę pisania komunikacji z BMP280 od zera, ale po konsultacji z notą katalogową i z przykładowymi sterownikami uznałem, że to nie jest tak łatwo jak z TC74, że od razu dostaje się wynk, tylko jest dużo zabawy z tym (kalibracje jakieś, obliczenia, przesunięcia bitowe) i ostatecznie użyłem biblioteki BMP280 od https://simple-circuit.com/ .
    Kod testowy:
    Code: c
    Log in, to see the code

    To naprawdę tylko tyle. Bardzo dobra biblioteka. Jedynie dodam, że mój skaner I2C się przydał, bo biblioteka miała wpisana domyślnie w nagłówku inny adres niż ten co miał mój czujnik.
    Ciśnienie:
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    Temperatura (przed i po podgrzaniu światłem):
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C

    Krok 14: sterowanie przekaźnikami
    Na koniec zrobiłem szkic sterowania przekaźnikami, a dokładnie tutaj przyjąłem format możliwości ustawienia zdarzeń, które zawierają:
    - czas (HH:MM:SS)
    - indeks przekaźnika
    - stan do ustawienia (on or off)
    Jednym z plusów takiego podejścia jest możliwość nadpisania stanu przekaźnika poprzez użytkownika (po prostu user może nacisnąć przycisk i przekaźnik wyłączyć)
    W kodzie użyłem konwencji z HH:MM:SS, chociaż tak jak pisałem wcześniej, pewnie docelowo będę trzymać tylko całkowitą ilość sekund z danej doby:
    Code: c
    Log in, to see the code

    W momencie zmiany sekundy sprawdzam ustawione zdarzenia i w razie czego wykonuję zmianę na pinie.
    To na razie wstępny szkic, ale docelowo rozważam rozdzielenie tego na alarmy (po prostu funkcjonalność budzika) oraz przekaźniki (załączanie dowolnego urządzenia).
    Do struktury relaySlot_t można by np. też dopisać konfigurowalną ilość w minutach po jakiej dany slot się wyłączy, też opcjonalnie, bo na ten moment jeśli chcemy coś włączać i wyłączać to trzeba użyć dwa sloty (jeden do zdarzenia ON, drugi dla OFF).
    Nie jest to sterowanie w pełni kompletne, brakuje jego wykonania oraz sposodu dostępu do GPIO. Reszta w drugiej częsci.

    Krok 15: złożone w całość
    Ostatecznie złożyłem w całość odliczanie czasu, pomiary temperatury i pomiary ciśnienia oraz szkic systemu ustawiania godziny oraz ustawiania zdarzeń.
    Normalnie zegar wyświetla bieżący czas, ale co około pół minuty pokazuje też ciśnienie w hPa (musiałem uciąć a przez brak miejsca na wyświetlaczu) oraz temperaturę (muszę dodać wyświetlanie kropki).
    Działa również edycja godziny i zdarzeń, bieżącą edytowaną wartość pokazuje kropka.
    Przy zdarzeniach edytujemy też Px (P0, P1, itd) jako numer przekaźnika/GPIO, oraz zmieniamy En na no (stan Enabled lub not active).
    Czas, ciśnienie, temperatura:



    Edycja godziny:



    Edycja przekaźnika (stan En/no, Px, godzina):



    Z tego co widzę, to chyba będę musiał pozwolić na częstsze wciśnięcia przycisków, bo zbyt częste kliknięcia się gubią.

    Krótka ściąga co dalej
    Inaczej zwana też potocznie "listą TODO", czyli to co jest do zrobienia za jakiś czas.
    - reorganizacja kodu
    - RTCC na I2C
    - dolutować LEDy w roli kropek do wyświetlaczy (bo akurat takie dostałem wyświetlacze...)
    - lepszy system przekaźników/alarmów
    - ustawienie daty i jej wyświetlanie
    - powrót z MikroC do SDCC (czyli ogarnięcie I2C w SDCC, bo to przez brak gotowego I2C tymczasowo zrobiłem migrację do Mikro)
    - rozważania co do PCB i przekaźników

    Podsumowanie
    To był trochę chaotyczny, trochę szczegółowy opis pierwszego etapu tworzenia zegara dla czytelnika. Projekt powstawał powoli, w wolnych chwilach, w formie takiej amatorskiej zabawy.
    Jeszcze raz dziękuję czytelnikowi za wysłanie mi części, zabawa była przednia (a to dopiero początek), tym bardziej, że dawno już chciałem coś porobić w starym stylu na PIC18F, bez żadnych WiFi, IoT i serwerów.
    Opis byłby dłuższy, ale już zbliżam się do limitu znaków w poście na forum (a taki u nas na Elektrodzie istnieje).
    W dalszej części spróbuję nieco ogarnąć kod, bo teraz tam miejscami jest źle, oraz wdrożyć system daty, już zapewne na zewnętrznym RTCC z bateryjką CR. Ulepszy się też system przekaźników/budzika, też przyda się dodać buzzer.
    Jak macie jakieś merytoryczne uwagi bądź sugestie jak np. lepiej zorganizować system kontroli przekaźnikami/budzikami/cokolwiek innego to zapraszam do komentowania.
    PS: Jeśli interesuje was nieco inne podejście do robienia zegara, tym razem z wyświetlaczem na MAX7219, to możecie zobaczyć mój temat sprzed 3 lat:
    Zegar/kalendarz na PIC16F1455, MAX7219, DS1302 - szczegółowy opis/kody/STLe. Tu chciałem nieco zrobić odmianę, z tego powodu realizuję całość inaczej.

    Cool? Ranking DIY
    Do you have a problem with Arduino? Ask question. Visit our forum Arduino.
    About Author
    p.kaczmarek2
    Moderator Smart Home
    Offline 
  • Computer Controls
  • Computer Controls
  • #3
    eurotips
    Level 39  
    Man jakiś słabszy dzień bo nijak nie czaję po co użyłeś drogiego PICa z USB skoro używasz TC74 który obsługujesz po I2C. A wersja obudowy, nie lepiej z większą ilością wyprowadzeń I/O niż zewnętrzny rejestr przesuwający.
  • #4
    yogi009
    Level 43  
    eurotips wrote:
    nie lepiej z większą ilością wyprowadzeń I/O niż zewnętrzny rejestr przesuwający?


    JA to odbieram pozytywnie, jako dodatkowy element edukacyjny. W końcu to nie jest jakiś przedprodukcyjny prototyp.
  • #5
    eurotips
    Level 39  
    p.kaczmarek2 wrote:
    początkowo pisałem na SDCC, ale potem by oszczędzić czasu przeniosłem się na MikroC

    Kogo stać na legalną licencję aby uruchomić zegarek LED ?
    yogi009 wrote:
    JA to odbieram pozytywnie, jako dodatkowy element edukacyjny. W końcu to nie jest jakiś przedprodukcyjny prototyp.

    No tak, zgoda, zegarek to edukacja ale MikroC to już komercja.
    To samo można zrobić na dowolnym Arduino, autora poniosło trochę, wypożyczył Bugatti Veyrona aby po fajki skoczyć do Biedry...
  • #6
    p.kaczmarek2
    Moderator Smart Home
    PIC18F2550, bo go mam na stanie, bo to na nim realizowałem kiedyś projekty, w tym mój klon PICKIT2 oraz Brenner 8. Trochę mi ich zostało, więc do tej pory ich się pozbywam przy każdej okazji, gdzie trzeba MCU do DIY to PIC18F2550 rusza do boju.

    MikroC w okrojonej wersji jest darmowe (limit rozmiaru programu), ale ogólnie to uwaga @eurotips w dużej mierze jest słuszna, tyle, że odpowiedź już jest podana w tekście - Mikro C użyłem by mieć szybciej ładne funkcje do I2C. Nie ma problemu by w któryś weekend wrócić do SDCC, wystarczy wziąć ładnie opakowane I2C stąd:
    https://github.com/PinguinoIDE/pinguino-libraries/tree/master/p8/include/pinguino/libraries

    Ale generalnie tak, pierwotny plan był zrobić to jako część tutorialu SDCC i nie używać wcale Mikro C, może do tego planu wrócę jak będzie wolny wieczór.

    Added after 3 [minutes]:

    Edit: Tu dokładnie jest I2C dla SDCC o którym pisałem:
    https://github.com/PinguinoIDE/pinguino-libraries/blob/master/p8/include/pinguino/core/i2c.c
    Nic nie stoi na przeszkodzie, by kolejną iterację projektu na tym odpalić, jak tak preferujecie.

    I ogólnie moim zdaniem to Mikro C tu najmniej zmienia, bo praktycznie wszystko byłoby takie same w SDCC. Nazwy rejestrów się troszeczkę zmieniają ale to dalej są te same rejestry, i tak dalej.

    Added after 8 [minutes]:

    EDIT: Tak teraz myślę, że jakby ktoś chciał, to można by w ogóle wziąć bootloader Pinguino i przez Pinguino IDE programować tego PICa...
    Budujemy zegar na PIC18F2550, krok po kroku - część 1, BMP280, TC74, 74HCT164, I2C
    To by ułatwiło też aktualizację wsadu bez PICKIT2... i może też rozważę tą opcję.

    Added after 5 [minutes]:


    Tu można poczytać o Pinguino:
    https://pinguino.cc/
    https://pinguino.cc/download/#for-gnu-linux
    Możliwe, że kolejna wersja projektu na tym wyjdzie, ze złączem USB z tyłu do aktualizacji softu.
  • #7
    Urgon
    Editor
    AVE...

    Odnośnie wyboru kompilatora, to ja bym proponował jednak użyć XC-8 od Microchip. Dodaje generator gotowych funkcji, i jeszcze zniesiono ograniczenia wersji darmowej.

    Co do PIC18F2550 i USB, to można mu załadować bootloader pozwalający na programowanie właśnie przez ten interfejs...