- Wymagane materiały:
- Wymagania wstępne:
- Schemat obwodu:
- Programowanie budzika:
- Symulacja:
- Działanie cyfrowego budzika za pomocą PIC16F877A:
Rewolucja cyfrowa, która rozpoczęła się w 1950 roku, zmienia wszystkie istniejące mechaniczne i analogowe struktury elektroniczne w komputery cyfrowe. Ponieważ rozwój elektroniki cyfrowej był wykładniczy, dziś jest prawie niemożliwe, aby człowiek oparł się używaniu jakiegokolwiek sprzętu elektronicznego. Począwszy od budzącego Cię budzika i tostera, który serwuje śniadanie, wszystko jest wkładem elektroniki cyfrowej. Myśląc o tym wszystkim, naprawdę ekscytujące jest programowanie własnych rzeczy, które mogłyby wykonywać proste, ale użyteczne zadania, takie jak budzik, który zamierzamy zbudować w tym projekcie z mikrokontrolerem PIC. Wcześniej zbudowaliśmy budzik z innymi mikrokontrolerami:
- Budzik Raspberry Pi przy użyciu modułu RTC DS1307
- Cyfrowy zegar oparty na Arduino z alarmem
- Budzik z mikrokontrolerem ATmega32
Ten budzik będzie miał wyświetlacz LCD 16x2, który wyświetli aktualny czas i ustawiony czas. W razie potrzeby użyjemy kilku przycisków, aby ustawić godzinę alarmu. Aktualny czas będzie śledzony za pomocą modułu DS3231 RTC i użyjemy komunikacji IIC, aby uzyskać te wartości z modułu RTC. Dowiedzieliśmy się już o module RTC i jak połączyć go z PIC. Dlatego zaleca się przeczytanie tego samouczka, pominiemy większość informacji zawartych w tym samouczku.
Wymagane materiały:
- Deska do chleba - 2 szt
- PIC16F877A
- Źródło zasilania 5V - moduł zasilający
- Kryształ 20 MHz
- Kondensator 33pf - 2
- Moduł DS3231 RTC
- Moduł wyświetlacza LCD 16 * 2
- 10K POT
- Rezystor 10k i 1K
- Przyciski - 5 szt
- Brzęczyk
- Przewody łączące
Wymagania wstępne:
Ten projekt wymaga znajomości kilku podstaw dotyczących mikrokontrolera PIC i jego programowania. W tym projekcie wykorzystamy GPIO, wyświetlacz LCD i moduł RTC. Dlatego lepiej wcześniej nauczyć się korzystać z tych modułów. Poniższe linki pomogą Ci się tego samego nauczyć
- Pisanie pierwszego programu z mikrokontrolerem PIC
- Interfejs LCD z PIC
- Komunikacja I2C za pomocą PIC
- Interfejs DS3231 RTC z PIC
Schemat obwodu:
Schemat obwodu dla tego projektu budzika opartego na PIC jest pokazany poniżej, który został utworzony przy użyciu oprogramowania proteus. Będzie również używany do symulacji w dalszej części projektu.
Pięć przycisków będzie działać jako wejście do ustawiania alarmu na wymagany czas. Tak więc jeden koniec wszystkich przycisków jest podłączony do masy, a pozostałe końce są podłączone do pinu PORTB, na tych pinach zostanie użyty wewnętrzny rezystor podciągający, aby uniknąć unoszenia się pinów. Brzęczyk będzie działał jako wyjście i wyda nam sygnał dźwiękowy, gdy alarm zostanie wyzwolony i zostanie podłączony do pinu PORT S. Aktualny czas jest zawsze śledzony przez moduł DS3231 RTC, z którego PIC odbiera dane przez magistralę I2C, więc piny SCL i SDA modułu RTC są podłączone do pinów SCL i SDA kontrolera PIC. Do PORTD PIC dołączony jest wyświetlacz LCD, który służy do wyświetlania aktualnego czasu i ustawionego czasu. Dowiedz się więcej o używaniu modułu DS3231 RTC z PIC tutaj.
Cały obwód można zbudować na płytce stykowej. Ponieważ do podłączenia jest kilkadziesiąt przewodów, po prostu bądź cierpliwy i upewnij się, że połączenia są prawidłowe. Moja konfiguracja sprzętu wyglądała mniej więcej tak poniżej, gdy skończyłem z połączeniami
Do zasilania modułu użyłem modułu płytki stykowej i adaptera 12V. To jest moje źródło napięcia zasilania + 5V. Muszę też użyć dwóch płytek stykowych, aby utrzymać obwód w czystości. Możesz również przylutować cały obwód do płyty perf, jeśli chcesz wykonać bardziej wytrzymały projekt.
Programowanie budzika:
Kompletny program PIC do tego projektu Budzik można znaleźć na dole tej strony. Ten projekt wymaga również trzech bibliotek do korzystania z LCD, I2C i RTC z PIC. Pełny kod z plikami nagłówkowymi można pobrać z pliku ZIP tutaj i można go otworzyć za pomocą MPLABX po rozpakowaniu. Dalej poniżej wyjaśniam tylko główny plik c jako małe fragmenty. Możesz wrócić do wyżej wymienionych samouczków, jeśli chcesz wiedzieć, jak działają pliki nagłówkowe.
Zanim przejdziemy do głównego programu, musimy zdefiniować piny, których używaliśmy, z bardziej zrozumiałą nazwą. W ten sposób będzie można z nich łatwo korzystać podczas programowania. Poniżej pokazane są piny zdefiniowane w naszym programie
// Określ szpilki LCD #define RS RD2 // reset pin LCD #define EN RD3 // Włącz pin LCD #define D4 RD4 // Dane bit 0 LCD #define D5 RD5 // dane bit 1 LCD #define D6 RD6 // Bit danych 2 LCD #define D7 RD7 // Data bit 3 of LCD // Definiuje przyciski #define MB RB1 // Środkowy przycisk #define LB RB0 // Lewy przycisk #define RB RB2 // Prawy przycisk # define UB RB3 // Górny przycisk #define BB RB4 // Dolny przycisk // Define Buzz #define BUZZ RD1 // Buzzer jest podłączony do RD1
Wewnątrz funkcji głównej zaczynamy od zadeklarowania pinów wejściowych i wyjściowych. W naszym projekcie PORTB jest używany do przycisków, które są urządzeniem wejściowym, więc ustawiamy ich piny jako wejścia, a PORTD jest używany dla LCD i brzęczyka, więc ustawiamy ich piny jako Wyjście. Również pin nigdy nie powinien pozostawać pływający, co oznacza, że piny I / O powinny być zawsze podłączone do uziemienia lub do napięcia + 5V. W naszym przypadku dla przycisków piny nie będą podłączone do niczego, gdy przycisk nie jest wciśnięty, więc używamy wewnętrznego rezystora podciągającego, który ustawia pin w stan wysoki, gdy nie jest używany. Odbywa się to za pomocą rejestrów kontrolnych, jak pokazano poniżej
TRISD = 0x00; // Ustaw piny Port D jako outptu dla interfejsu LCD TRISB = 0xFF; // Przełączniki są deklarowane jako piny wejściowe OPTION_REG = 0b00000000; // Włącz rezystor podciągający w porcie B dla przełączników BUZZ = 0; // Wyłącz brzęczyk
Ponieważ mamy plik nagłówkowy LCD i I2C powiązany z głównym programem, możemy rozpocząć inicjalizację LCD, wywołując prostą funkcję. To samo można zrobić dla inicjalizacji I2C. Tutaj rozpoczynamy komunikację I2C na 100kHz, ponieważ moduł RTC pracuje na 100kHz.
Lcd_Start (); // Inicjalizacja modułu LCD I2C_Initialize (100); // Zainicjuj I2C Master z zegarem 100 KHz
Poniższa funkcja służy do ustawiania czasu i daty w module RTC, po ustawieniu godziny i daty usuń tę linię. W przeciwnym razie za każdym razem, gdy uruchomisz program, godzina i data będą ustawiane ponownie
// Usuń poniższą linię, gdy godzina i data zostaną ustawione po raz pierwszy. Set_Time_Date (); // ustaw czas i datę w module RTC
Aby wskazać, że program się uruchamia, wyświetlamy mały ekran powitalny, który wyświetla nazwę projektu i nazwę strony internetowej, jak pokazano poniżej
// Podaj wiadomość wprowadzającą na LCD Lcd_Clear (); Lcd_Set_Cursor (1,1); Lcd_Print_String ("Budzik"); Lcd_Set_Cursor (2,1); Lcd_Print_String ("-Circuit Digest"); __delay_ms (1500);
Następny wewnątrz while pętli musimy odczytać aktualny czas i datę z modułu RTC, można to zrobić tylko przez wywołanie funkcji poniżej.
Update_Current_Date_Time (); // Odczytaj aktualną datę i godzinę z modułu RTC
Wywołanie powyższej funkcji zaktualizuje zmienne sec, min i hour o bieżącą wartość. Aby wyświetlić je na ekranie LCD, musimy podzielić je na poszczególne znaki za pomocą poniższego kodu.
// Podziel znak na znak do wyświetlenia na lcd char sec_0 = sec% 10; char sec_1 = (sec / 10); char min_0 = min% 10; char min_1 = min / 10; char godzina_0 = godzina% 10; char hour_1 = godzina / 10;
Następnie aktualizujemy wartości na ekranie LCD. Bieżący czas zostanie wyświetlony w pierwszej linii, a ustawiony czas, w którym alarm ma zostać wyzwolony, wyświetlany jest w drugiej linii. Kod, który robi to samo, pokazano poniżej.
// Wyświetl aktualny czas na ekranie LCD Lcd_Clear (); Lcd_Set_Cursor (1, 1); Lcd_Print_String ("CZAS:"); Lcd_Print_Char (godzina_1 + „0”); Lcd_Print_Char (godzina_0 + „0”); Lcd_Print_Char (':'); Lcd_Print_Char (min_1 + '0'); Lcd_Print_Char (min_0 + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (sec_1 + '0'); Lcd_Print_Char (sec_0 + '0'); // Wyświetl datę na ekranie LCD Lcd_Set_Cursor (2, 1); Lcd_Print_String ("Alarm:"); Lcd_Print_Char (wartość_alarmu + '0'); Lcd_Print_Char (wartość_alarmu + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (wartość_alarmu + '0 '); Lcd_Print_Char (wartość_alarmu + '0');
Teraz, gdy wyświetliliśmy godzinę i ustawiony czas na LCD, musimy sprawdzić, czy użytkownik próbuje ustawić godzinę alarmu. Aby to zrobić, użytkownik musi nacisnąć środkowy przycisk, więc sprawdzimy, czy środkowy przycisk jest wciśnięty i przełączymy zmienną, aby wejść w tryb ustawiania alarmu. Ten sam przycisk zostanie ponownie wciśnięty, aby potwierdzić, że wartości są ustawione iw takim przypadku musimy wyjść z trybu ustawiania alarmu. Dlatego używamy poniższego wiersza kodu, aby zmienić stan zmiennej set_alarm .
// Użyj środkowego przycisku, aby sprawdzić, czy alarm ma być ustawiony if (MB == 0 && set_alarm == 0) {// Jeśli środkowy przycisk jest wciśnięty i alarm nie jest włączony while (! MB); // Poczekaj, aż przycisk zostanie zwolniony set_alarm = 1; // rozpoczęcie ustawiania wartości alarmu } if (MB == 0 && set_alarm == 1) {// Jeśli naciśnięto środkowy przycisk i alarm nie został wyłączony while (! MB); // Poczekaj, aż przycisk zostanie zwolniony set_alarm = 0; // zatrzymaj ustawianie wartości alarmu }
Jeśli użytkownik nacisnął środkowy przycisk, oznacza to, że próbuje ustawić godzinę alarmu. W tym przypadku program przechodzi w tryb ustawiania alarmu przy użyciu powyższego kodu. W trybie ustawiania alarmu, jeśli użytkownik naciśnie lewy lub prawy przycisk, oznacza to, że musimy przesunąć kursor w lewo lub w prawo. Aby to zrobić, po prostu zwiększamy lub zmniejszamy wartość pozycji, w której ma zostać umieszczony kursor
if (LB == 0) {// Jeśli lewy przycisk zostanie naciśnięty podczas (! LB); // Poczekaj, aż przycisk zostanie zwolniony pos--; // Następnie przesuń kursor w lewo } if (RB == 0) {// Jeśli prawy przycisk zostanie naciśnięty podczas (! RB); // Poczekaj, aż przycisk zostanie zwolniony pos ++; // Przesuń kursor w prawo }
Podczas korzystania z przycisku z mikrokontrolerem lub mikroprocesorem istnieje jeden wspólny problem do rozwiązania. Ten problem jest nazywany odbijaniem się przełączników. Dzieje się tak, gdy przycisk jest wciśnięty, może on dawać hałaśliwe impulsy do MCU / MPU, które mogą fałszywie MCU dla wielu wpisów. Ten problem można rozwiązać, dodając kondensator na przełączniku lub używając funkcji opóźnienia, gdy tylko zostanie wykryte naciśnięcie przycisku. Tego typu rozwiązanie nazywa się de-bouncingiem. Tutaj użyliśmy while pętli do przechowywania programu w miejscu, aż do zwolnienia przycisku. To nie jest najlepsze rozwiązanie odbijające, ale dla nas będzie działać dobrze.
podczas gdy (! RB);
Podobnie jak lewy i prawy przycisk, mamy również górny i dolny przycisk, którym możemy zwiększyć lub zmniejszyć wartość czasu alarmu. Kod umożliwiający to samo pokazano poniżej. Zauważ, że każdy znak ustawionego czasu alarmu jest adresowany przez wartość indeksu tablicy. Dzięki temu możemy łatwo uzyskać dostęp do wymaganego znaku, którego wartości należy zmienić.
if (UB == 0) {// Jeśli górny przycisk zostanie naciśnięty podczas (! UB); // Poczekaj, aż przycisk zostanie zwolniony alarm_val ++; // Zwiększ tę konkretną wartość znaku } if (BB == 0) {// Jeśli dolny przycisk zostanie naciśnięty podczas (! UB); // Poczekaj, aż przycisk zostanie zwolniony alarm_val--; // Zmniejsz tę konkretną wartość znaku }
Po ustawieniu godziny alarmu użytkownik ponownie naciśnie środkowy przycisk. Następnie możemy rozpocząć porównywanie aktualnego czasu z ustawionym czasem. Porównanie poprzez sprawdzenie, czy każdy pojedynczy znak aktualnego czasu jest równy znakowi ustawionego czasu. Jeśli wartości są równe, wyzwalamy alarm, ustawiając zmienną trigger_alarm, w przeciwnym razie porównujemy, aż stanie się równa.
// JEŻELI alarm jest ustawiony Sprawdź, czy ustawiona wartość jest równa aktualnej wartości if (set_alarm == 0 && alarm_val == godzina_1 && alarm_val == godzina_0 && alarm_val == min_1 && alarm_val == min_0) trigger_alarm = 1; // Włącz wyzwalacz, jeśli wartość pasuje
Jeśli alarm jest ustawiony, musimy nadać sygnał dźwiękowy, aby ostrzec użytkownika o alarmie. Można to zrobić, po prostu przełączając Buzzer w regularnych odstępach czasu, jak pokazano poniżej.
if (trigger_alarm) {// Jeśli zostanie uruchomiony alarm // Sygnał dźwiękowy BUZZ = 1; __delay_ms (500); BUZZ = 0; __delay_ms (500); }
Symulacja:
Ten program można również symulować za pomocą oprogramowania proteus. Po prostu ponownie utwórz obwód pokazany powyżej i załaduj plik hex do PIC. Kod szesnastkowy tego projektu można znaleźć w pliku ZIP, który jest tutaj połączony. Zrzut ekranu wykonany podczas symulacji pokazano poniżej
Symulacja staje się bardzo przydatna, gdy próbujesz dodać nowe funkcje do projektu. Możesz również użyć modułu debuggera I2C, aby sprawdzić, jakie dane wchodzą i wychodzą przez magistralę I2C. Możesz spróbować nacisnąć przyciski, a także ustawić godzinę alarmu. Gdy ustawiony czas jest równy aktualnemu czasowi, brzęczyk włączy się w stan wysoki.
Działanie cyfrowego budzika za pomocą PIC16F877A:
Zbuduj obwód na płytce prototypowej, pobierz kod z linku pobierania i skompiluj go za pomocą kompilatora MplabX i XC8. Jeśli pobrałeś kod z podanego tutaj pliku ZIP, nie powinieneś mieć problemu z jego kompilacją, ponieważ pliki nagłówkowe są już dołączone.
Po skompilowaniu prześlij program na swój sprzęt za pomocą programatora PicKit3. Połączenie do podłączenia programatora pickit do PIC IC jest również pokazane na schemacie obwodu. Po załadowaniu programu powinieneś zobaczyć ekran powitalny, a następnie wyświetlaną godzinę, możesz następnie za pomocą przycisków ustawić godzinę alarmu. Moja konfiguracja sprzętu przy zasilaniu wygląda następująco.
Gdy godzina alarmu zgadza się z aktualną godziną, brzęczyk zacznie wydawać sygnał dźwiękowy, aby zaalarmować użytkownika. Całość pracy można znaleźć na poniższym filmie. Projekt ma wiele opcji do wykorzystania. Moduł RTC może śledzić dowolny czas i datę, dzięki czemu można wykonać zaplanowane zadanie w dowolnym wymaganym czasie / dniu. Możesz również podłączyć urządzenie AC, takie jak wentylator lub światło, i zaplanować jego włączenie lub wyłączenie w razie potrzeby. Jest jeszcze wiele rzeczy, które możesz zbudować na podstawie tego projektu, daj mi znać, jaki pomysł przyjdzie Ci do głowy jako ulepszenie tego projektu, a ja z przyjemnością Cię wysłucham.
Mam nadzieję, że zrozumiałeś projekt i nauczyłeś się czegoś przydatnego z tego procesu. Jeśli masz jakiekolwiek wątpliwości w tym projekcie, skorzystaj z sekcji komentarzy, aby je opublikować lub skorzystaj z forum, aby uzyskać pomoc techniczną.
Pełny kod PIC z plikami nagłówkowymi można znaleźć tutaj