- Erforderliche Materialien:
- Voraussetzungen:
- Schaltplan:
- Programmierung für Wecker:
- Simulation:
- Funktionsweise des digitalen Weckers mit PIC16F877A:
Die 1950 begonnene digitale Revolution verwandelt alle vorhandenen mechanischen und analogen elektronischen Strukturen in digitale Computer. Da das Wachstum der digitalen Elektronik exponentiell war, ist es heute für eine Person fast unmöglich, sich der Verwendung elektronischer Geräte zu widersetzen. Angefangen vom Wecker, der Sie weckt, bis zum Toaster, der Ihnen das Frühstück serviert, ist alles ein Beitrag der digitalen Elektronik. Wenn man an all dies denkt, ist es wirklich aufregend, unsere eigenen Sachen zu programmieren, die einfache, aber nützliche Aufgaben erledigen können, wie den Wecker, den wir in diesem Projekt mit PIC Microcontroller bauen werden. Wir haben zuvor einen Wecker mit anderen Mikrocontrollern gebaut:
- Raspberry Pi Wecker mit RTC-Modul DS1307
- Arduino-basierte Digitaluhr mit Alarm
- Wecker mit ATmega32 Mikrocontroller
Dieser Wecker verfügt über ein 16x2-LCD-Display, auf dem die aktuelle Uhrzeit und die eingestellte Uhrzeit angezeigt werden. Wir werden einige Drucktasten verwenden, um die Alarmzeit bei Bedarf einzustellen. Die aktuelle Zeit wird mithilfe des DS3231-RTC-Moduls aufgezeichnet, und wir verwenden die IIC-Kommunikation, um diese Werte vom RTC-Modul abzurufen. Wir haben bereits etwas über das RTC-Modul und dessen Schnittstelle mit PIC gelernt. Es wird daher empfohlen, dieses Lernprogramm durchzulesen. Wir werden die meisten Informationen in diesem Lernprogramm überspringen.
Erforderliche Materialien:
- Brotbrett - 2Nos
- PIC16F877A
- 5V Stromquelle - Versorgungsmodul
- 20 MHz Kristall
- 33pf Kondensator - 2Nos
- DS3231 RTC-Modul
- 16 * 2 LCD-Anzeigemodul
- 10K POT
- 10k und 1K Widerstand
- Druckknöpfe - 5Nos
- Summer
- Kabel anschließen
Voraussetzungen:
Für dieses Projekt müssen Sie einige Grundlagen über den PIC-Mikrocontroller und dessen Programmierung kennen. Für dieses Projekt werden GPIOs, LCD-Display und RTC-Modul verwendet. Es ist daher besser, vorher zu lernen, wie man diese Module benutzt. Die folgenden Links helfen Ihnen dabei, dasselbe zu lernen
- Schreiben Sie Ihr erstes Programm mit PIC Microcontroller
- LCD mit PIC verbinden
- I2C-Kommunikation über PIC
- DS3231 RTC-Schnittstelle mit PIC
Schaltplan:
Das Schaltbild für dieses PIC-basierte Weckerprojekt ist unten dargestellt, das mit der Proteus-Software erstellt wurde. Das wird in diesem Projekt auch für die weitere Simulation verwendet.
Die fünf Drucktasten dienen als Eingang zum Einstellen des Alarms für die erforderliche Zeit. Damit ein Ende aller Drucktasten mit Masse und die anderen Enden mit dem PORTB-Pin verbunden sind, wird an diesen Pins ein interner Pull-up-Widerstand verwendet, um ein Schweben der Pins zu vermeiden. Der Summer fungiert als Ausgang und gibt einen Piepton aus, wenn der Alarm ausgelöst wird und mit dem PORT S-Pin verbunden ist. Die aktuelle Zeit wird immer vom DS3231-RTC-Modul verfolgt, von dem der PIC die Daten über den I2C-Bus empfängt, sodass die SCL- und SDA-Pins des RTC-Moduls mit dem SCL- und SDA-Pin des PIC-Controllers verbunden sind. Am PORTD des PIC ist eine LCD-Anzeige angebracht, mit der die aktuelle Uhrzeit und die eingestellte Zeit angezeigt werden. Weitere Informationen zur Verwendung des DS3231-RTC-Moduls mit PIC finden Sie hier.
Die gesamte Schaltung kann über ein Steckbrett aufgebaut werden. Da ein paar Dutzend Drähte angeschlossen werden müssen, haben Sie einfach Geduld und stellen Sie sicher, dass die Verbindungen korrekt sind. Meine Hardware-Einrichtung sah ungefähr so aus, als ich mit den Verbindungen fertig war
Ich habe ein Steckbrettmodul und einen 12-V-Adapter verwendet, um das Modul mit Strom zu versorgen. Dies ist meine Quelle für + 5V Versorgungsspannung. Außerdem muss ich zwei Steckbretter verwenden, um die Schaltung sauber zu halten. Sie können auch die gesamte Schaltung auf eine Perf-Platine löten, wenn Sie ein robusteres Projekt erstellen möchten.
Programmierung für Wecker:
Das vollständige PIC-Programm für dieses Weckerprojekt finden Sie unten auf dieser Seite. Für dieses Projekt sind außerdem drei Bibliotheken für die Verwendung von LCD, I2C und RTC mit PIC erforderlich. Der vollständige Code mit den Header-Dateien kann hier aus der ZIP-Datei heruntergeladen und nach dem Extrahieren mit MPLABX geöffnet werden. Weiter unten erkläre ich nur die Haupt-C-Datei als kleine Schnipsel. Sie können auf die oben genannten Tutorials zurückgreifen, wenn Sie wissen möchten, wie die Header-Dateien funktionieren.
Bevor wir in das Hauptprogramm einsteigen, müssen wir die Pins definieren, die wir mit einem aussagekräftigeren Namen verwendet haben. Auf diese Weise ist es einfach, sie während der Programmierung zu verwenden. Die in unserem Programm definierten Pins sind unten gezeigt
// Definieren Sie die LCD-Pins #define RS RD2 // Setzen Sie den Pin des LCD zurück #define EN RD3 // Aktivieren Sie den Pin des LCD #define D4 RD4 // Datenbit 0 des LCD #define D5 RD5 // Datenbit 1 des LCD #define D6 RD6 // Datenbit 2 des LCD #define D7 RD7 // Datenbit 3 des LCD // Tasten definieren #define MB RB1 // Die mittlere Taste #define LB RB0 // linke Taste #define RB RB2 // rechte Taste # UB RB3 definieren // Obere Taste # BB RB4 definieren // Untere Taste // Buzz definieren # BUZZ RD1 definieren // Summer ist mit RD1 verbunden
Innerhalb der Hauptfunktion deklarieren wir zunächst die Eingangs- und Ausgangspins. In unserem Projekt wird der PORTB für Drucktasten verwendet, bei denen es sich um ein Eingabegerät handelt. Daher setzen wir ihre Pins als Eingänge und PORTD für LCD und Summer, sodass wir ihre Pins als Ausgang setzen. Außerdem sollte ein Pin niemals schwebend bleiben, was bedeutet, dass die E / A-Pins immer entweder mit Masse oder mit der + 5V-Spannung verbunden sein sollten. In unserem Fall für die Druckknöpfe werden die Stifte mit nichts verbunden, wenn der Knopf nicht gedrückt wird. Daher verwenden wir einen internen Pull-up-Widerstand, der den Stift auf High setzt, wenn er nicht verwendet wird. Dies erfolgt unter Verwendung der Steuerregister wie unten gezeigt
TRISD = 0x00; // Port D-Pins als Ausgang für die LCD-Schnittstelle festlegen TRISB = 0xFF; // Schalter werden als Eingangspins deklariert OPTION_REG = 0b00000000; // Pull-up- Widerstand an Port B für Schalter aktivieren BUZZ = 0; // Summer ausschalten
Da die LCD- und I2C-Headerdatei mit dem Hauptprogramm verknüpft ist, können wir die LCD-Initialisierung durch Aufrufen einer einfachen Funktion starten. Das Gleiche gilt auch für die I2C-Initialisierung. Hier starten wir die I2C-Kommunikation bei 100 kHz, da das RTC-Modul mit 100 kHz arbeitet.
Lcd_Start (); // LCD-Modul initialisieren I2C_Initialize (100); // I2C Master mit 100KHz Takt initialisieren
Mit der folgenden Funktion können Sie Uhrzeit und Datum auf dem RTC-Modul einstellen. Wenn Uhrzeit und Datum eingestellt sind, entfernen Sie diese Zeile. Andernfalls werden bei jedem Programmstart Uhrzeit und Datum immer wieder eingestellt
Entfernen Sie die folgende Zeile // einmal Zeit und Datum werden zum ersten Mal eingestellt. Set_Time_Date (); // Uhrzeit und Datum auf dem RTC-Modul einstellen
Um anzuzeigen, dass das Programm gestartet wird, wird ein kleiner Einführungsbildschirm angezeigt, auf dem der Name des Projekts und der Name der Website wie unten gezeigt angezeigt werden
// Eine Intro-Nachricht auf dem LCD geben Lcd_Clear (); Lcd_Set_Cursor (1,1); Lcd_Print_String ("Wecker"); Lcd_Set_Cursor (2,1); Lcd_Print_String ("-Circuit Digest"); __delay_ms (1500);
Als nächstes müssen wir innerhalb der while- Schleife die aktuelle Uhrzeit und das aktuelle Datum aus dem RTC-Modul lesen. Dies kann durch einfaches Aufrufen der folgenden Funktion erfolgen.
Update_Current_Date_Time (); // Lesen Sie das aktuelle Datum und die aktuelle Uhrzeit vom RTC-Modul
Durch Aufrufen der obigen Funktion werden die Variablen sec, min und hour mit dem aktuellen Wert aktualisiert. Um sie auf dem LCD-Bildschirm anzuzeigen, müssen wir sie mit dem folgenden Code in einzelne Zeichen aufteilen.
// Teilen Sie das in Zeichen auf, das auf dem LCD- Zeichen angezeigt werden soll. Sec sec_0 = sec% 10; char sec_1 = (sec / 10); char min_0 = min% 10; char min_1 = min / 10; char hour_0 = Stunde% 10; char Stunde_1 = Stunde / 10;
Als nächstes aktualisieren wir die Werte über den LCD-Bildschirm. Die aktuelle Uhrzeit wird in der ersten Zeile angezeigt und die eingestellte Zeit, zu der der Alarm ausgelöst werden muss, wird in der zweiten Zeile angezeigt. Der Code, der dasselbe tut, wird unten gezeigt.
// Aktuelle Zeit auf dem LCD-Bildschirm anzeigen Lcd_Clear (); Lcd_Set_Cursor (1, 1); Lcd_Print_String ("TIME:"); Lcd_Print_Char (Stunde_1 + '0'); Lcd_Print_Char (Stunde_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'); // Datum auf dem LCD-Bildschirm anzeigen Lcd_Set_Cursor (2, 1); Lcd_Print_String ("Alarm:"); Lcd_Print_Char (alarm_val + '0'); Lcd_Print_Char (alarm_val + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (alarm_val + '0 '); Lcd_Print_Char (alarm_val + '0');
Jetzt haben wir die Uhrzeit und die eingestellte Zeit auf dem LCD angezeigt. Wir müssen prüfen, ob der Benutzer versucht, die Alarmzeit einzustellen. Dazu muss der Benutzer die mittlere Taste drücken. Wir werden also prüfen, ob die mittlere Taste gedrückt ist, und eine Variable umschalten, um in den Alarmeinstellungsmodus zu gelangen. Dieselbe Taste wird erneut gedrückt, um zu bestätigen, dass die Werte eingestellt sind. In diesem Fall müssen wir den Alarmeinstellmodus verlassen. Daher verwenden wir die folgende Codezeile, um den Status der Variablen set_alarm zu ändern.
// Mit der mittleren Taste prüfen, ob ein Alarm eingestellt werden muss, wenn (MB == 0 && set_alarm == 0) {// Wenn die mittlere Taste gedrückt wird und der Alarm nicht eingeschaltet wird, während (! MB); // Warte bis die Taste losgelassen wird set_alarm = 1; // Alarmwert einstellen } if (MB == 0 && set_alarm == 1) {// Wenn die mittlere Taste gedrückt wird und der Alarm nicht ausgeschaltet wird, während (! MB); // Warte bis die Taste losgelassen wird set_alarm = 0; // Einstellung des Alarmwerts beenden }
Wenn der Benutzer die mittlere Taste gedrückt hat, bedeutet dies, dass er versucht, die Alarmzeit einzustellen. In diesem Fall wechselt das Programm mit dem obigen Code in den Alarmeinstellungsmodus. Wenn der Benutzer im Alarmeinstellungsmodus die linke oder rechte Taste drückt, bedeutet dies, dass wir den Cursor nach links oder rechts bewegen müssen. Dazu erhöhen wir einfach den Wert der Position, an der der Cursor platziert werden muss
if (LB == 0) {// Wenn die linke Taste gedrückt wird, während (! LB); // Warte bis die Taste losgelassen wird pos--; // Bewegen Sie dann den Cursor nach links } if (RB == 0) {// Wenn die rechte Taste gedrückt wird, während (! RB); // Warte bis die Taste losgelassen wird pos ++; // Cursor nach rechts bewegen }
Bei Verwendung eines Druckknopfs mit einem Mikrocontroller oder Mikroprozessor ist ein häufiges Problem zu lösen. Dieses Problem wird als Switch Bouncing bezeichnet. Wenn die Taste gedrückt wird, werden möglicherweise verrauschte Impulse an die MCU / MPU ausgegeben, wodurch die MCU für mehrere Einträge gefälscht werden kann. Dieses Problem kann durch Hinzufügen eines Kondensators über dem Schalter oder durch Verwenden einer Verzögerungsfunktion gelöst werden, sobald der Tastendruck erkannt wird. Diese Art der Lösung wird als Entprellen bezeichnet. Hier haben wir eine while- Schleife verwendet, um das Programm an Ort und Stelle zu halten, bis die Taste losgelassen wird. Dies ist keine beste Lösung zum Abprallen, aber für uns wird es gut funktionieren.
während (! RB);
Ähnlich wie bei der linken und rechten Taste haben wir auch die obere und untere Taste, mit denen Sie den Wert der Alarmzeit erhöhen oder verringern können. Der Code, um dasselbe zu tun, ist unten gezeigt. Beachten Sie, dass jedes Zeichen der eingestellten Alarmzeit durch den Indexwert des Arrays adressiert wird. Auf diese Weise können wir leicht auf das gewünschte Zeichen zugreifen, dessen Werte geändert werden müssen.
if (UB == 0) {// Wenn die obere Taste gedrückt wird, während (! UB); // Warte bis die Taste losgelassen wird alarm_val ++; // Erhöhe diesen bestimmten Zeichenwert } if (BB == 0) {// Wenn die untere Taste gedrückt wird, während (! UB); // Warte bis die Taste losgelassen wird alarm_val--; // Diesen bestimmten Zeichenwert verringern }
Sobald die Alarmzeit eingestellt ist, drückt der Benutzer erneut die mittlere Taste. Dann können wir beginnen, die aktuelle Zeit mit der eingestellten Zeit zu vergleichen. Der Vergleich durch Überprüfen, ob jedes einzelne Zeichen der aktuellen Zeit dem Zeichen der eingestellten Zeit entspricht. Wenn die Werte gleich sind, lösen wir den Alarm aus, indem wir die Variable trigger_alarm setzen. Andernfalls vergleichen wir nur, bis sie gleich wird.
// WENN Alarm gesetzt ist Überprüfen Sie, ob der eingestellte Wert gleich dem aktuellen Wert ist, wenn (set_alarm == 0 && alarm_val == hour_1 && alarm_val == hour_0 && alarm_val == min_1 && alarm_val == min_0) trigger_alarm = 1; // Trigger einschalten, wenn Wert übereinstimmt
Wenn der Alarm eingestellt ist, müssen wir den Summer piepen, um den Benutzer auf einen Alarm aufmerksam zu machen. Dies kann durch einfaches Umschalten des Summers in regelmäßigen Abständen erfolgen, wie unten gezeigt.
if (trigger_alarm) {// Wenn ein Alarm ausgelöst wird // Signalton BUZZ = 1; __delay_ms (500); BUZZ = 0; __delay_ms (500); }}
Simulation:
Dieses Programm kann auch mit der Proteus-Software simuliert werden. Erstellen Sie einfach die oben gezeigte Schaltung neu und laden Sie die Hex-Datei in den PIC. Den Hex-Code für dieses Projekt finden Sie in der hier verlinkten ZIP-Datei. Ein Screenshot, der während der Simulation aufgenommen wurde, ist unten dargestellt
Die Simulation ist sehr nützlich, wenn Sie versuchen, dem Projekt neue Funktionen hinzuzufügen. Sie können auch das I2C-Debugger-Modul verwenden, um zu überprüfen, welche Daten über den I2C-Bus ein- und ausgehen. Sie können versuchen, die Tasten zu drücken und auch die Alarmzeit einzustellen. Wenn die eingestellte Zeit gleich der aktuellen Zeit ist, geht der Summer hoch.
Funktionsweise des digitalen Weckers mit PIC16F877A:
Bauen Sie die Schaltung auf dem Steckbrett auf, holen Sie sich den Code über den Download-Link und kompilieren Sie ihn mit dem MplabX- und XC8-Compiler. Wenn Sie den Code aus der hier bereitgestellten ZIP-Datei heruntergeladen haben, sollten Sie keine Probleme beim Kompilieren haben, da die Header-Dateien bereits angehängt sind.
Laden Sie das Programm nach dem Kompilieren mit dem PicKit3-Programmierer auf Ihre Hardware hoch. Die Verbindung zum Anschließen des Pickit-Programmiergeräts an den PIC-IC ist ebenfalls im Schaltplan dargestellt. Nachdem das Programm hochgeladen wurde, sollten Sie den Intro-Bildschirm sehen und dann die angezeigte Zeit. Mit den Drucktasten können Sie die Alarmzeit einstellen. Meine Hardware-Einrichtung im eingeschalteten Zustand sieht wie folgt aus.
Wenn die Alarmzeit mit der aktuellen Zeit übereinstimmt, ertönt ein Signalton, um den Benutzer zu alarmieren. Die komplette Arbeit finden Sie im Video unten. Das Projekt bietet eine Vielzahl von Optionen, auf denen aufgebaut werden kann. Das RTC-Modul kann jede Uhrzeit und jedes Datum verfolgen, sodass Sie eine geplante Aufgabe jederzeit ausführen können. Sie können ein AC-Gerät auch wie einen Lüfter oder eine Lampe anschließen und bei Bedarf ein- oder ausschalten. Sie können noch viel mehr auf dieses Projekt aufbauen. Lassen Sie mich wissen, welche Idee Ihnen als Upgrade für dieses Projekt in den Sinn kommt, und ich freue mich, von Ihnen zu hören.
Ich hoffe, Sie haben das Projekt verstanden und dabei etwas Nützliches gelernt. Wenn Sie irgendwelche Zweifel an diesem Projekt haben, verwenden Sie den Kommentarbereich, um sie zu posten, oder verwenden Sie die Foren für technische Hilfe.
Den vollständigen PIC-Code mit Header-Dateien finden Sie hier