Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

DCF77-Analysator/Uhr v2.0

Komponenten und Verbrauchsmaterialien

Arduino Mega 2560
× 1
Arduino UNO
× 1

Über dieses Projekt

Nachdem ich die Arduino-Plattform entdeckt hatte, war ich erstaunt und mein Traum, eines Tages meine eigene Elektronik zu entwickeln, wurde wahr.

Wie es jeder tun wird, begann ich mit den grundlegenden Skizzen, aber bald wollte ich etwas Nützliches machen. Da ich Funkuhren schon immer geliebt habe (in meinem Fall synchronisieren sie sich mit dem DCF77-Signal aus Deutschland), habe ich mich entschlossen, eine Uhr zu bauen, die nicht nur die Zeit anzeigt, sondern mir auch anzeigt, was vor sich geht.

Nach Hunderten von Stunden Basteln und unzähligen Fehlern hatte ich endlich eine funktionierende Uhr mit meinem eigenen Code und Leiterplattendesigns.

Fotos und Videos von DCF77 Analyzer/Clock v1.0:

Später entdeckte ich aber den DCF77 Superfilter von Udo Klein, der ein sauberes Signal liefert, wenn das Funksignal nicht so gut ist.

Dies ist ein separates Arduino Uno-Board mit der Superfilter-Software (Sie können es als eigenständige "Black Box" betrachten, die das Signal filtert), die zwischen der DCF77-Antenne und dem Arduino Mega angeschlossen ist, auf dem meine Skizze ausgeführt wird.

Also habe ich eine 2.0-Version der ersten Uhr erstellt:

  • komplett neu geschriebener Code
  • ausführlich kommentiert, damit hoffentlich jeder versteht, was los ist
  • PIR-Bewegungssensor hinzugefügt, um den Stromverbrauch zu reduzieren
  • DCF77 Superfilter hinzugefügt
  • zusätzliche Anzeige für Temperatur oder andere Verwendungen (wie Sonnenaufgang/Sonnenuntergang)

Fotos und Videos des neuen DCF77 Analyzer/Clock v2.0:

Demo

Um das Video anzusehen, klicken Sie HIER

'Standuhr' einbauen

Um das Video anzusehen, klicken Sie HIER

Das Design

Die Frontplatte und das Gehäuse:

Das Design der Frontplatte wurde in einem Freeware-Programm namens Inkscape erstellt (siehe Download-URL am Anfang dieser Seite).

Die eigentliche Herstellung der Frontplatte erwies sich als der schwierigste Teil. Ich habe viel Geld ausgegeben, um es in einem lokalen FabLab mit einem Laserschneider und einer speziellen Art von Acryl mit einer aluminiumähnlichen Beschichtung herzustellen. Die Idee war, die Löcher mit dem Laser zu schneiden und den Text und die Linien zu gravieren, indem die sehr dünne Beschichtung weggebrannt wurde, die das schwarze Acryl darunter freilegte. Dies war jedoch ein Albtraum, da der Laserschneider aufgrund der starken Beanspruchung und des "Missbrauchs" durch viele Benutzer nicht in der Lage war, innerhalb der von mir benötigten Toleranzen zu produzieren.

Dann bin ich auf einen Online-Fotodienst gestoßen. Sie drucken auf allen möglichen Materialien und eines davon war eine DiBond-Platte. Der Preis war sehr gut, 28 Euro inklusive Porto. Aber das Ergebnis war zunächst enttäuschend, da mein Design nicht 1:1 gedruckt, sondern leicht vergrößert wurde. Passen Sie also auf, wenn Sie sich für diese Methode entscheiden. Rufen Sie zuerst an und fragen Sie, ob es möglich ist, 1:1 zu drucken.

Nach einem Telefonat schickten sie mir ein weiteres Panel mit den richtigen Abmessungen. Es war besser als erwartet, ausgezeichnet!

Dann war viel Bohren und Fräsen nötig:

Code

  • DCF-Analysator / Uhr v2.1
  • Superfilter-Skizze
DCF-Analysator / Uhr v2.1Arduino
2020-01-18 Bug Release:Energiesparschalter behoben
/* ===============================================================================DCF77-Analysator / Uhr Version 2 ==============================================================================Diese Skizze ist freie Software; Sie können es unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren; entweder Version 2.1 der Lizenz oder (nach Ihrer Wahl) eine spätere Version. Diese Skizze wird in der Hoffnung verteilt, dass sie nützlich ist, jedoch OHNE JEGLICHE GEWÄHRLEISTUNG; auch ohne die stillschweigende Garantie der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. Weitere Informationen finden Sie in der GNU Lesser General Public License. Zusammen mit dieser Bibliothek sollten Sie eine Kopie der GNU Lesser General Public License erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==============================================================================Dieser C++-Code ist alles andere als optimiert, da ich selbst ein Arduino- und C++-Neuling bin. Aber auch nachdem ich jetzt etwas mehr gelernt habe, möchte ich den Code einfach und lesbar halten. Aus diesem Grund habe ich den Code möglicherweise überdokumentiert, um zu verstehen, was vor sich geht. Erik de Ruiter 2014-2020 Mai 2014 Erste Version März 2016 - große Überholung... Juli 2016 - Beginn mit dem Bau der 2.0 Uhr und Anpassung der Skizze Version 2.1 Datum 18.01.2020 - Powersafe-Funktion behoben. Version 2.0 - Diese Skizze ist für meine 2.0-Version der DCF/Analyzer Clock angepasst. Es verwendet standardmäßig den Arduino MEGA und den DCF-Superfilter und um die vielen separaten LEDs anzusteuern, verwende ich jetzt die Ports eines Arduino Mega anstelle eines Maxim 7219-Chips. Dies liegt daran, dass das Ansteuern von LEDs mit vielen verschiedenen Spannungs- / Stromspezifikationen mit dem Maxim-Chip problematisch ist. Das Anzünden zusätzlicher LEDs zum Beispiel beeinflusst (dimmt) die bereits eingeschalteten LEDs. Da ich kein Elektroniker bin, bestand meine einzige Lösung darin, die zusätzlichen Ports des Arduino Mega zu verwenden. Natürlich können Sie Transistoren oder zusätzliche Chips verwenden, um die LEDs anzusteuern, aber für mich war dies die offensichtliche Lösung. - Alle Anzeigecodes der Maxim Common Anode Version 1.72 entfernt - Option:Verwenden Sie einen billigen Ebay-PIR-Detektor, um auswählbare Anzeigen auszuschalten, wenn keine Aktivität festgestellt wird. Die Ausschaltverzögerung kann vom Benutzer eingestellt werden, um das Abschalten des Displays zu verhindern, wenn sich eine Person nicht bewegt, das Display aber eingeschaltet sein sollte. - Jetzt kann die Anzeige Nachtabschaltung deaktiviert werden, indem die beiden Werte 'POWERSAVINGOFFTIME' und 'POWERSAVINGONTIME' auf Null gesetzt werden. - Behoben, dass die Temperaturanzeige im Energiesparmodus nicht ausgeschaltet wurde. - errorCounter-Anzeige wurde nicht stündlich zurückgesetzt -fixiert Version 1.71 - Benutzeroption zum Zurücksetzen des Temperatur-Min/Max-Speichers um Mitternacht Version 1.7:- Die Auflösung der Temperaturanzeige wurde verbessert:von 0,5 auf 0,1 Grad Celsius Aufgrund der Zeit des DS18B20-Sensors Um die Temperatur umzuwandeln und den Code sauber zu halten, wird die Temperaturanzeige einmal pro Minute aktualisiert. - Paritätsprüfroutine optimiert. - Zuverlässigere Prüfung auf fehlerhafte DCF-Daten, um RTC-Updates mit ungültigen Daten zu verhindern. - EoB-Fehler löscht jetzt den inneren LED-Ring wie er sollte. - Die DCF OK LED zeigt nun zuverlässiger den Zustand des DCF Signals an. Schaltet sich sofort aus, wenn ein Fehler auftritt und schaltet sich nur ein, wenn alle 3 Paritätsbits in Ordnung sind. Version 1.6:- Geänderte Temperaturfunktion, um nur einmal pro Minute zu berechnen. Habe vor der Änderung seltsame Fehler bekommen, weil ich eine Verzögerung von 100 ms verwendet habe, um dem DS18B20-Sensor Zeit zum Berechnen der Temperatur zu geben. Aber die Verzögerungsfunktion ist in den meisten C++-Codes eine sehr schlechte Idee, also habe ich sie endlich losgeworden. Version 1.5:- Komplette Überarbeitung der scanSignal-Funktion und des restlichen Codes! Mein erster Versuch funktionierte, könnte aber verbessert werden... - Die rPW- und rPT-LEDs funktionierten nicht wie beabsichtigt, das ist jetzt korrigiert. - Die Fehlerprüfroutine für das Ende des Puffers funktioniert jetzt wie sie sollte. - Ich habe eine Paritätsprüfung des eingehenden DCF-Signals eingebaut. Im Signal werden 3 Paritätsbits gesendet, also werden diese nun überprüft und nur wenn alle drei in Ordnung sind, wird die empfangene Zeitinformation übernommen, die Anzeige aktualisiert und die RTC synchronisiert. Falls gewünscht, können Sie 3 zusätzliche zweifarbige LEDs (Common Cathode) anschließen, um zu sehen, ob jedes der 3 Paritätsbits OK oder Failed ist. - Ich habe die Verkabelung (oder das Ändern der Verkabelung) viel einfacher gemacht, denke ich, indem ich die gesamte PIN-Konfiguration in eine leicht lesbare Tabelle gepackt habe - Solange Sie 1 DS18B20 temp. Sensor habe ich den Code bearbeitet, damit Sie die Adresse des I2C-Geräts nicht mehr herausfinden müssen. - Großes Aufräumen des Codes... - Stromsparen durch Abschalten der Displays (die Uhr läuft normal weiter) kann jetzt etwas einfacher konfiguriert werden, indem man zwei Variablen POWERSAVINGONTIME und POWERSAVINGOFFTIME editiert. - einige Variablennamen geändert:- Maxim Instanzen 'lc' und 'lc1' sind jetzt MaximCC und MaximCA - Displaybeschreibung MaximDcfTime ist jetzt DisplayTempWeek - DCF77SOUNDPIN ist jetzt BUZZERSWITCHPIN - LED/Display Test nach dem Einschalten jetzt eingebaut Kurzbeschreibung:Power On:Nach dem Einschalten wird zunächst ein LED-Test durchgeführt. Die LEDs und Anzeigen leuchten nacheinander auf, um den Stromverbrauch gering zu halten. Dann beginnt die Uhr, DCF-Impulse zu empfangen, und wenn eine Minutenmarkierung (2 Sekunden Lücke) erkannt wird, leuchtet die Minutenmarkierungs-LED und der Pufferzähler wird zurückgesetzt. Der innere LED-Ring zeigt nun die eingehenden DCF-Impulse an, die auch im Puffer gespeichert werden. Zu drei Zeitpunkten während des Datenempfangs werden die Paritäts-DCF-Bits überprüft, um zu sehen, ob die Daten gültig sind. Gültige Daten empfangen:Wenn am Ende der Minute, nachdem die Minute Mark erkannt wurde (BF (Buffer Full) LED leuchtet), alle drei Paritätsbits OK sind ('DCF OK' LED leuchtet), sind die Pufferinformationen verwendet, um Zeit- und Datumsinformationen zu extrahieren. Dann wird die RTC-Uhr aktualisiert ('RTC Synced'-LED leuchtet) und die Informationen des inneren LED-Rings werden in den äußeren LED-Ring kopiert. Die Zeit-, Datums- und Wochenanzeige, Tag-LED, Sommer-/Winterzeit und Schaltjahr-LED-Informationen werden mit den neuen Zeitinformationen aktualisiert. Keine gültigen Daten:Wenn eines oder mehrere der Paritätsbits aufgrund eines verrauschten Signals nicht in Ordnung sind, wird der Empfang von DCF-Informationen fortgesetzt, aber nicht zum Aktualisieren der RTC, der Anzeige und der LEDs verwendet. Der äußere LED-Ring, die LEDs „RTC synced“ und „DCF OK“ werden zurückgesetzt. Uhrzeit, Datum, Woche, Tag-LED, Sommer-/Winterzeit-LED und Schaltjahr-LED sind davon nicht betroffen und zeigen weiterhin die zuletzt empfangenen gültigen Werte an. Die Fehler-LEDs „Periode Zeit“ und/oder „Periode mit“ zeigen den/die Fehler an und die Anzeige des Fehlerzählers wird aktualisiert. Jede Stunde wird die Fehleranzeige auf Null gesetzt. Die EoB, End of Buffer LED leuchtet, wenn mehr DCF-Impulse empfangen werden, bevor die Minutenmarke aufgrund eines verrauschten Signals erkannt wird. (Wenn eine Minutenmarkierung erkannt wird, sollten wir nicht mehr als 58 Bits/Impulse haben) Nach der Erkennung der Minutenmarkierung wird ein neuer Zyklus gestartet. Temperatur:Bei der 30-Sekunden-Marke zeigt die Temperaturanzeige die Höchst- und Tiefstwerte des letzten Zeitraums nach dem letzten Zurücksetzen an. Glockenspiel:Wenn der GLOCKEN-Schalter auf ON/HIGH steht, ertönt zu Beginn jeder Stunde das Glockenspiel (sofern angeschlossen). Nachts, eine Zeit, die vom Benutzer im Code selbst eingestellt wird, ist das Glockenspiel deaktiviert. Energiesparmodus - Display wird ausgeschaltet Dies funktioniert nur, WENN der Energiesparschalter HOCH ist:1. NACHT AUS Zu den vom Benutzer eingestellten Zeiten werden die Displays nachts ausgeschaltet und morgens eingeschaltet. Sehen Sie sich die Variablen POWERSAVINGOFFTIME und POWERSAVINGONTIME an. Aktivieren Sie die Funktion , um auszuwählen, WELCHE Displays Sie nachts ausschalten möchten. 2. PIR-SENSOR Schließen Sie einen PIR-Sensor an und aktivieren Sie die PIR-Option POWERSAVE_BY_PIR und die Verzögerung bei PIR_DELAY_TIME. Jedes Mal, wenn der PIR-Melder eine Bewegung erkennt, wird ein Minutenzähler zurückgesetzt, aber wenn länger als die PIR_DELAY_TIME keine Bewegung erkannt wird, werden die Anzeigen abgeschaltet. Bei Bewegung schalten sich die Displays sofort ein. Hinweis:Wie bereits erwähnt, funktioniert die Uhr normal, wenn die Displays ausgeschaltet sind. DCF-Beep:Mit einem Schalter, der an Pin BUZZERSWITCHPIN angeschlossen ist, können Sie die empfangenen DCF-Bits ankommen hören. Die Tondauer entspricht der Impulsbreite der DCF-Bits, also entweder 100 oder 200 ms. Sonstiges:Wenn die RTC-Batterie leer ist oder ein Verbindungsfehler erkannt wird, leuchtet die RTC-Error-LED. CREDITS:Ich habe viel von der Arbeit von Matthias Dalheimer und Thijs Elenbaas gelernt, die ihre eigenen DCF77-Decoder entwickelt haben. Ohne ihre Arbeit hätte ich nicht gewusst, wo ich anfangen soll. Am Ende habe ich meinen eigenen Code geschrieben (unter Verwendung von Teilen ihrer Ideen), damit ich verstehen konnte, was passiert ... Mein Code ist alles andere als effizient oder fortschrittlich, aber er funktioniert und ich weiß, was vor sich geht. Interessante Websites:- Brett Oliver:http://home.btconnect.com/brettoliver1/ - Joop Tap:http://www.jooptap.nl - Thijs Ellenbaas:http://thijs.elenbaas.net/2012/04/ arduino-dcf77-radio-clock-receiver-hardware-2/ - Mathias Dalheimer :https://github.com/roddi/DCF77-Arduino/blob/master/DCF77Servoclock/DCF77.h - DCF77 wikipedia :https://en .wikipedia.org/wiki/DCF77 - Viele weitere DCF77-Infos:http://www.picbasic.nl/indexes_uk.htm - Meine Flickr-Website:https://www.flickr.com/photos/edr1924/albums - Mein Github Website:https://github.com/deruiter *///----------------------------------- -------------------------------------------------- ----------------------// Bibliotheken//------------------------ -------------------------------------------------- --------------------------------- // Arduino (neu) Zeitbibliothek .......... .......................... http://www.pjrc.com/teensy/td_libs_Time.html#include // Aktivieren Sie diese Zeile, wenn Sie Arduino Uno, Mega usw. verwenden. #include  // eine grundlegende DS1307-Bibliothek y, das Zeit als time_t zurückgibt .......... http://www.pjrc.com/teensy/td_libs_DS1307RTC.html#include // Maxim 7219 zeigt Bibliothek an ..... ................................ http://playground.arduino.cc/Main/LEDMatrix// !!! HINWEIS:Sie müssen eine spezielle Version der Ledcontrol.h-Bibliothek verwenden, um Common Anode-Unterstützung zu erhalten // da der Maxim-Chip normalerweise nur für gängige CATHODE-Displays geeignet ist!#include //SPI-Schnittstellenbibliothek .... ...................................... http://arduino.cc/en/Reference/ SPI#include // OneWire ermöglicht den Zugriff auf 1-Wire-Geräte von Maxim/Dallas,// wie DS18S20, DS18B20, DS1822 .................. ............. http://www.pjrc.com/teensy/td_libs_OneWire.html// Die DallasTemperature-Bibliothek kann all diese Arbeit für Sie erledigen! ... http://milesburton.com/Dallas_Temperature_Control_Library#include //----------------------------- -------------------------------------------------- ---------------------------// Arduino UNO Pin-Anschlüsse in einer gut lesbaren Tabelle //// Eingang - Rx - wird für die Programmierung verwendet /Kommunikation mit PC// Ausgang - Tx - verwendet für Programmierung/Kommunikation mit PC#define DCF77PIN 2 // Eingang - DCF-Signal von der Antennenplatine. Pin muss ein Interrupt-Eingang sein!#define PIRDETECTORPIN 3 // Eingang - PIR-Detektor:Auf Aktivität im Raum prüfen, um Displays zu aktivieren#define BUZZERSWITCHPIN 4 // Eingang - SWITCH - DCF77 'Beep' Piezo-Summer ein-/ausschalten / ON =HIGH , OFF =LOW#define CHIMESWITCHPIN 5 // Eingabe - SWITCH - Ein-/Ausschalten des stündlichen Glockentons / ON =HIGH, OFF =LOW#define POWERSAVESWITCHPIN 6 // Eingabe - SWITCH - Ein-/Ausschalten der Energiesparfunktion, damit Anzeige ist immer an / ON =HIGH, OFF =LOW#define TEMPSENSORPIN 8 // Eingang - Dallas One Wire DS18B20 Temperatursensor#define TEMPRESETPIN 9 // Eingang - PUSH BUTTON - Temperatur Min/Max Speicher zurücksetzen / HIGH =reset#define MAXIMCCLD 10 // Ausgabe - CS/LOAD - Pseudo-SPI-Verbindung zum Maxim 7219-Chip - 7-Segment-Anzeigen#define MAXIMCCCLK 11 // Ausgabe - CLOCK - Pseudo-SPI-Verbindung zum Maxim 7219-Chip - 7-Segment-Anzeigen#define MAXIMCCDATA 12 // Ausgabe - DATA - Pseudo-SPI-Verbindung zum Maxim 7219-Chip - 7-Segment-Anzeigen// !! Pins 22 bis 53 sind nur für LEDs zu verwenden#define LED_SUNDAY 22 // Ausgang - LED - Sonntag#define LED_MONDAY 23 // Ausgang - LED - Montag#define LED_TUESDAY 24 // Ausgang - LED - Dienstag#define LED_WEDNESDAY 25 // Ausgang - LED - Mittwoch#define LED_DONNERSTAG 26 // Ausgang - LED - Donnerstag#define LED_FRIDAY 27 // Ausgang - LED - Freitag#define LED_SATURDAY 28 // Ausgang - LED - Samstag#define LED_CEST 29 // Ausgang - LED - Sommerzeit MESZ #define LED_CET 30 // Ausgang - LED - Winterzeit MEZ#define LED_LEAPYEAR 31 // Ausgang - LED - Schaltjahr#define LED_RTCERROR 32 // Ausgang - LED - Problem beim Lesen der RTC-Daten (Batterie leer/Verbindung)#define LED_RTCSYNC 33 // Ausgang - LED - An, wenn RTC erfolgreich mit der DCF-Zeit synchronisiert wurde#define LED_TEMP 34 // Ausgang - LED - Temperatur wird angezeigt#define LED_OPTION1 35 // Ausgang - LED - optional 1 Daten werden angezeigt#define LED_OPTION2 36 // Ausgang - LED - optional 2 Daten werden angezeigt#define LED_ERRORPT 37 // Ausgang - LED - DCF Period Time error#define LED_ ERRORPW 38 // Ausgabe - LED - DCF-Periodenbreite error#define LED_BUFFERFULL 39 // Ausgabe - LED - Anzeige Puffer voll, als nächstes werden die Daten analysiert#define LED_MINUTEMARKER 40 // Ausgabe - LED - Ende des DCF-Datenstroms vor Puffer erkannt ist gefüllt, Daten sind beschädigt#define LED_BUFFEROVERFLOW 41 // Ausgabe - LED - Mehr Daten in einer Minute empfangen als erwartet aufgrund eines schlechten Signals#define LED_DCFSTATUS 42 // Ausgabe - LED - An, wenn wir gute DCF-Daten haben#define LED_POWERSAVE 43 / / Ausgabe - LED - Stromsparmodus ist aktiviert, einige Anzeigen sind aus#define LED_PARITY1PASS 44 // Ausgabe - LED - Parität 1 Bit ist OK#define LED_PARITY1FAIL 45 // Ausgabe - LED - Parität 1 Bit FAILED#define LED_PARITY2PASS 46 // Ausgang - LED - Parität 2 Bit ist OK#define LED_PARITY2FAIL 47 // Ausgang - LED - Parität 2 Bit FAILED#define LED_PARITY3PASS 48 // Ausgang - LED - Parität 3 Bit ist OK#define LED_PARITY3FAIL 49 // Ausgang - LED - Parität 3 Bit FAILED#define LED_PIRMOTION 50 // Ausgang - LED - Ein wenn PIR Bewegung erkennt/ / Analoge Pins#define BUZZER A7 // Ausgang - Piezo-Summer für DCF77 'Beep' (an '+' des Summers)#define SPEAKERVOLPIN A6 // Ausgang - Soundboard-Lautstärke - LOW =Lautstärke eine Stufe tiefer. SPEAKERVOLUME legt fest, wie oft dieser Ausgang nach dem Einschalten aktiviert wird#define CHIMEPIN A5 // Ausgabe - Chime Activate - OUTPUT LOW =Aktivieren Sie Chime auf Adafruit Soundboard FX // USED for DS1307 RTC // I2C DATA - connect to Real Time Clock PCB/ / VERWENDET für DS1307 RTC // I2C CLOCK - Verbindung zur Echtzeituhr-Platine //-------------------------------- -------------------------------------------------- ------------------------- // DS18B20-Initialisierung //-------- -------------------------------------------------- ------------------------------------OneWire ds(TEMPSENSORPIN); // Onewire-Instanz DS definieren //------------------------------------------------------ -------------------------------------------------- -------------- // Maxim 7219 Matrix Display Initialisierung // ------------------ -------------------------------------------------- ------------------------------------------/* clearDisplay(int adr) .............. ............................... löscht die ausgewählte Anzeige MaximCC.shutdown(int addr, boolean) ...... .......................... Wecken des MAX72XX aus dem Energiesparmodus (true =sleep, false =wach) MaximCC.setIntensity(int addr , Wert) ................................ eine mittlere Helligkeit für die LEDs einstellen (0=min - 15=max) MaximCC .setLed(int addr, int row, int col, boolean state) .......... Schaltet die LED in Zeile, Spalte ein. Denken Sie daran, dass Indizes bei 0 beginnen! MaximCC.setRow(int addr, int row, byte value) ...................... diese Funktion benötigt 3 Argumente. Beispiel:MaximCC.setRow(0,2,B101100000); MaximCC.setColumn(int addr, int col, byte value) ................... diese Funktion benötigt 3 Argumente. Beispiel:MaximCC.setColumn(0,5,B00001111); MaximCC.setDigit(int addr, int digit, byte value, boolean dp) ...... diese Funktion nimmt ein Argument vom Typ byte und gibt die entsprechende Ziffer in der angegebenen Spalte aus. Der gültige Wertebereich reicht von 0..15. Alle Werte zwischen 0..9 werden als Ziffern ausgegeben, Werte zwischen 10..15 werden als ihr hexadezimales Äquivalent ausgegeben MaximCC.setChar(int addr, int digit, char value, boolean dp) ....... zeigt an:0 1 2 3 4 5 6 7 8 9 ABCDEFHLP; - . , _  (das Leer- oder Leerzeichen) POWERSAVESWITCHPIN ***** Bitte geben Sie die Anzahl der Geräte an, die Sie haben ***** Aber die maximale Standardeinstellung von 8 MAX72XX wird auch funktionieren. LedConrol(DATAIN, CLOCK, CS/LOAD, NUMBER OF MAXIM CHIPS) */// lc ist für das Maxim DisplaysLedControl MaximCC =LedControl(MAXIMCCDATA, MAXIMCCCLK, MAXIMCCLD, 7, false); // Definiere Pins für Maxim 72xx und wie viele 72xx wir verwenden //---------------------------------- -------------------------------------------------- -------------------// Benutzereinstellungen, Variablen- und Array-Definitionen//----------------- -------------------------------------------------- -------------------------------------------------- // Der Wert unten ist keine PIN-Nummer, sondern a Wert, um einzustellen, wie oft der Eingang 'Lautstärke verringern' am Soundboard aktiviert wird // damit die Lautstärke des Soundboards nach dem Einschalten auf Wunsch verringert werden kann.#define SPEAKERVOLUME 12// Wählen Sie, ob Sie a Test aller LEDs und Displays nach einem Start// '1' =Ja, '0' =Nein#define PERFORM_LED_TEST 1// Verzögerung zwischen jeder 7-Segment-Anzeige in ms#define LEDTEST_DELAY_DISPLAYS 600// Verzögerung zwischen jeder LED im LED-Ring und andere LEDs in ms#define LEDTEST_DELAY_LED_RING 20 // Wählen Sie, ob Sie den DS18B20-Temperatursensor EINMAL auf die höchste Auflösung konfigurieren möchten. // dies wird nach der Verwendung des Sensors für die Tanne benötigt st mal. Nachdem Sie die Software// mit dieser Einstellung ON einmal ausgeführt haben, schalten Sie sie aus.// '1' =ON, '0' =OFF#define CONFIGURE_DS18B20 0// POWERSAVE TIME - OBLIGATORISCHE Werte! //// um Tag und . zu definieren Nachtzeit. Dies wird für die Ein- und Ausschaltzeit des Energiespardisplays verwendet // UND um zu bestimmen, ob der Gong aktiviert wird (tagsüber). //// NUR die Displays werden zur Energiesparzeit ausgeschaltet, die Uhr bleibt voll aktiv./ / UM das Ausschalten des Displays jederzeit zu DEAKTIVIEREN, einfach den Energiesparschalter auf OFF stellen //// Energiesparschalter ON:Displays werden zur eingestellten Nachtzeit ausgeschaltet // UND wenn POWERSAVE_BY_PIR Funktion aktiviert und vorhanden ist keine // Bewegung für die eingestellte PIR_DELAY_TIME.// Energiesparschalter OFF:Displays immer an, Glockenschlag nur tagsüber.//// Werte sind im 'Stunden'-Format, also 20 Uhr ist '20', NICHT 20:00 oder 20:00...#define POWERSAVINGOFFTIME 9 // Displays werden aktiviert#define POWERSAVINGONTIME 22 // Displays werden ausgeschaltet // Benutzeroption:Aktivieren der Displays nur bei Aktivität im Raum // '1' =ON, '0 ' =OFF#define POWERSAVE_BY_PIR 1// Verzögerung in MINUTEN, um nach keiner Erkennung zu warten, bevor die Displays abgeschaltet werden#define PIR_DELAY_TIME 30// Benutzeroption zum Zurücksetzen der Temperatur min /max. Speicher um Mitternacht// '1' =Reset um Mitternacht, '0' =Nur manuelles Zurücksetzen#define TEMPRESET_MIDNIGHT 1//------------------------ -------------------------------------------------- -------// Definiere verschiedene Parameter#define DS1307_I2C_ADDRESS 0x68 // Definiere die RTC I2C Adresse#define DCF_INTERRUPT 0 // Interrupt Nummer verbunden mit Pin // Definition der Maxim 7219 Displaynummer Verdrahtungssequenz// erstes Maxim 7219 in Verdrahtung 'Daisychain' muss '0' sein, nächste '1' usw. // COMMON CATHODE DISPLAYS#define LedRingInner 0#define LedRingOuter 1#define DisplayBufferBitError 2#define DisplayPeriodPulse 3#define DisplayTempWeek 4#define DisplayDate 6 5#define DisplayTime / Definition der Helligkeitsstufen des Displays#define BrightnessLedRingOuter 1#define BrightnessLedRingInner 1#define BrightnessDisplayTime 1#define BrightnessDisplayDate 7#define BrightnessDisplayTempWeek 15#define BrightnessDisplayPeriodPulse 2#define BrightnessDisplayBufferBitError 15// Pulse flanksd unsigned 0 long führenden tatic unsigned long TrailingEdge =0;unsigned long previousLeadingEdge =0;// verwendet in volatile unsigned int DCFSignalState =0; // Interrupt-Variablen benötigen IMMER einen flüchtigen Qualifizierer!!// verwendet in 
int previousSecond =0;unsigned int previousSignalState =0;// DCF-Puffer und -Indikatorenstatic int DCFbitBuffer[59]; // hier werden die empfangenen DCFbits gespeichertconst int bitValue[] ={1, 2, 4, 8, 10, 20, 40, 80}; // dies sind die dezimalen Werte der empfangenen DCFbits// erst nach Start einer neuen Minute, empfangene Bits auf der inneren LED anzeigen ringboolean MinuteMarkerFlag =false;int bufferPosition =0;int previousMinute =0;int previousHour =0;// variables um zu prüfen ob DCF-Bits sind valdbool dcfValidSignal =false;int dcfP1counter =0;int dcfP2counter =0;int dcfP3counter =0;int dcfParityCheckP1 =0;int dcfParityCheckP2 =0;int dcfParityCheckP3dF Zeitvariablen speichern/ . dekodiert zu/ inint dcfMinute =0;int dcfHour =0;int dcfDay =0;int dcfWeekDay =0;int dcfMonth =0;int dcfYear =0;int dcfDST =0;int jumpYear =0;// Variablen zum Speichern von Wochen- und Tageszahlenwertenint dayNumber;int WeekNumber;// Fehlerzählervariableint errorCounter =0;boolean errorCondition =false;// miscelleanous variablesboolean daytimeChange =true;boolean dayTime =false;int dcf77SoundSwitch =0;// Temperaturvariablenbyte vorhanden =0;Byte DS18B20Data[12];int maxTemp =0;int minTemp =0;int lowByte =0;int hi ghByte =0;float tempReading =0;int tempCelsius =0;boolean tempResetButton =false;// PIR-Detektorvariablenint pirActivity =0;int pirDisplaysState =1;unsigned int pirTimer =0;unsigned long previousTimePIR =0;//============================================================================// SETUP//============================================================================void setup () {// Initialisieren der seriellen Kommunikation Serial.begin (9600); // PIN-Verbindungen initialisieren PinMode (DCF77PIN, INPUT); pinMode (TEMPRESETPIN, EINGANG); pinMode (SUMMERSCHALTERPIN, EINGANG); pinMode (CHIMESWITCPIN, EINGANG); pinMode (POWERSAVESWITCHPIN, INPUT); pinMode (PIRDETECTORPIN, EINGANG); pinMode (CHIMEPIN, AUSGANG); pinMode (LAUTSPRECHERVOLPIN, AUSGANG); // LED-Pins 22 - 50 für (int i1 =22; i1 <=50; i1++) initialisieren {pinMode (i1, OUTPUT); } // Variablen, LED-Anzeigen und LEDs initialisieren initialize(); // Initialisieren Sie den DCF77-Impulsinterrupt an Pin DCF_INTERRUPT und suchen Sie nach einer Änderung des Signals, // sodass entweder steigende oder fallende Flankenimpulse den Interrupt-Handler auslösen und // die int0handler-Funktion ausführen. attachInterrupt(DCF_INTERRUPT, int0handler, CHANGE); // RTC initialisieren und als SyncProvider festlegen. // Später wird RTC mit der DCF-Zeit synchronisiert setSyncProvider(RTC.get); // die Funktion zum Abrufen der Uhrzeit von der RTC // prüfen, ob RTC die Systemzeit eingestellt hat if (timeStatus() !=timeSet) { // Synchronisation mit der RTC nicht möglich - RTCError aktivieren LED digitalWrite(LED_RTCERROR, HIGH); } else {// RTC hat die Systemzeit eingestellt - dim RTCError LED digitalWrite (LED_RTCERROR, LOW); } // Nach dem Einschalten die Lautsprecherlautstärke des Adafruit Audio Boards einstellen // beide Pins auf LOW initialisieren, was der Standardausgangszustand ist digitalWrite (SPEAKERVOLPIN, LOW); digitalWrite (CHIMEPIN, NIEDRIG); // niedrigere Soundboard-Standardlautstärke mit 'SPEAKERVOLUME'-Schritten für (int i =0; i <=SPEAKERVOLUME; i++) { digitalWrite (SPEAKERVOLPIN, HIGH); Verzögerung (100); digitalWrite (LAUTSPRECHERVOLPIN, NIEDRIG); Verzögerung (100); } // Die folgende Funktion sollte nur einmal ausgeführt werden. // Es wird verwendet, um die Temperaturauflösung des DS18B20-Sensors zu konfigurieren, wenn (CONFIGURE_DS18B20 ==1) {configureDS18B20 (); } // zu Testzwecken verwenden und/oder die RTC-Zeit manuell einstellen // setTime(23, 59, 40, 31, 12, 13); // RTC.set (jetzt ()); // Die Temperaturumrechnung anfordern computeTemp(); // prüfen, ob ein LED-Test erforderlich ist if (PERFORM_LED_TEST ==1) { // LED-Test durchführen ledTest(); } else {// Wenn kein LED-Test durchgeführt wird, müssen wir etwas warten, bis der DS18B20-Sensor bereit ist Verzögerung (750); } // Jetzt die Temperatur vom Sensor abrufen und anzeigen displayTemp(); // errorCounter-Anzeige nach LED-Test aktivieren ledDisplay(DisplayBufferBitError, "R", 0);}//===========================================================================// SCHLEIFE//============================================================================Void loop () {// zuerst prüfen, ob die Pulsrichtung geändert wird (steigend oder fallen) // sonst würden wir denselben Impuls weiter auswerten if (DCFSignalState !=previousSignalState) { // 'Zurücksetzen' Zustand der Variablen previousSignalState =DCFSignalState; // eingehenden Impuls auswerten scanSignal (); } // prüfen, ob Schalter geändert wurden und darauf reagieren checkSwitches(); // auf PIR-Bewegung prüfen checkPIR (); // Aufgaben ausführen, die nur einmal pro Sekunde, Minute oder Stunde passieren dürfen //--------------------------------- ------------------------------------------------------- taskEverySecond(); AufgabenEveryMinute(); AufgabenJede Stunde();}//=============================================================================================================//// Funktionsname :processDcfBit// aufgerufen von ://// Zweck :Wertet das empfangene Signal aus. Entscheidet, ob wir eine "1" oder eine "0" erhalten haben// und prüft, ob das Pulstiming innerhalb der Grenzen liegt// Parameter :keine// Rückgabewert :keine////============================================================================================================/* Puls Pulsbreite |- -| |-- --| |----- ENDE DER MINUTE-Markierung:2000ms -----| ___ _______ ___ ___ _______ | 0 | | 1 | | 0 | | 0 | | 1 | | | | | | | | | | | | | | | | | | | | | ______| |_______________| |___________| |___________________________________| |_______________| |__ _ _ _ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 1000 2100 2000 2200 3000 3100 KEIN PULSE 5000 5100 6000 6200 < REJECTED error(LED_ERRORPW); errorCondition =true; } //-------------------------------------------------------------------------------- // CHECK PULSE TIME //-------------------------------------------------------------------------------- // If the detected pulse is too short it will be an incorrect pulse that we shall reject // should be 100 and 200 ms ideally if (((trailingEdge - leadingEdge) <70) || ((trailingEdge - leadingEdge)> 230)) { //rPT - ERROR:Pulse Width too short or too long -> REJECTED error(LED_ERRORPT); errorCondition =true; } // if we had an error return and start over if (errorCondition ==true) { errorCondition =false; // although we have an error, store current rising edge time to compare at the next Rising-Edge. previousLeadingEdge =leadingEdge; Rückkehr; } //-------------------------------------------------------------------- // no errors found so now we can continue //-------------------------------------------------------------------- // first we turn any error Led's OFF digitalWrite(LED_ERRORPW, LOW); digitalWrite(LED_ERRORPT, LOW); digitalWrite(LED_BUFFERFULL, LOW); // previous BF digitalWrite(LED_BUFFEROVERFLOW, LOW); // previous EoB digitalWrite(LED_MINUTEMARKER, LOW); // previous EoM // END OF MINUTE check, looking for a gap of approx. 2000ms if (leadingEdge - previousLeadingEdge> 1900 &&leadingEdge - previousLeadingEdge <2100) { // end of minute detected:finalizeBuffer(); } // refresh previousLeadingEdge time with the new leading edge time previousLeadingEdge =leadingEdge; //-------------------------------------------------------------------------------- // process DCF bits //-------------------------------------------------------------------------------- // distinguish between long and short pulses if (trailingEdge - leadingEdge <170) { // call processDcfBit function and sent it the value '0' processDcfBit(0); // if switch is HIGH, the DCF pulses are audible if (dcf77SoundSwitch ==1) buzzer(100); } else { // call processDcfBit function and sent it the value '1' processDcfBit(1); // if switch is HIGH, the DCF pulses are audible if (dcf77SoundSwitch ==1) buzzer(200); } } // if (DCFSignalState ==0)} // void scanSignal();//================================================================================================================//// Function name :processDcfBit// called from ://// Purpose :after reception of one good DCF bit, do some checks and save it in the DCFbitBuffer array// Parameters :none// Return value :none////================================================================================================================void processDcfBit(int dcfBit){ //-------------------------------------------------------------------- // display values on the 7 segment displays //-------------------------------------------------------------------- // display bufferPosition, digits 7,6 MaximCC.setChar(DisplayBufferBitError, 7, bufferPosition / 10, false); MaximCC.setChar(DisplayBufferBitError, 6, bufferPosition % 10, false); // display received DCFbit, digit 4 MaximCC.setChar(DisplayBufferBitError, 4, dcfBit, false); //-------------------------------------------------------------------- // display incoming DCF bits on inner LED ring //-------------------------------------------------------------------- // only if we have valid DCF data or after an Minute Mark (EoM) signal // activate the inner LED ring and diplay incoming data if (dcfValidSignal ==true || MinuteMarkerFlag ==true) { // display received bits on inner LED ring MaximCC.setLed(LedRingInner, bufferPosition / 8, bufferPosition % 8, dcfBit); } //-------------------------------------------------------------------- // // Fill DCFbitBuffer array with DCFbit //-------------------------------------------------------------------- DCFbitBuffer[bufferPosition] =dcfBit; //-------------------------------------------------------------------- // Parity check //-------------------------------------------------------------------- // DURING reception of the DCF bits, calculate and display the results of the DCF parity check. // // There is a Parity bit for the minutes, the hours and for the date. // DCF77 works with EVEN parity, this works as follows:// The hours for example have 6 bits plus a paritybit. The bits with value 1 are add up including the paritybit, // the result must be an even number. If there is a bit wrong received, a 0 is as 1, or a 1 is as 0 received, // then the result is uneven. source:http://www.picbasic.nl/frameload_uk.htm?http://www.picbasic.nl/info_dcf77_uk.htm if (bufferPosition ==0) { // reset the parity LED's digitalWrite(LED_PARITY1PASS, LOW); digitalWrite(LED_PARITY1FAIL, LOW); digitalWrite(LED_PARITY2PASS, LOW); digitalWrite(LED_PARITY2FAIL, LOW); digitalWrite(LED_PARITY3PASS, LOW); digitalWrite(LED_PARITY3FAIL, LOW); // reset variables dcfP1counter =0; dcfP2counter =0; dcfP3counter =0; dcfParityCheckP1 =0; dcfParityCheckP2 =0; dcfParityCheckP3 =0; } // ---------------------------------------- // First parity check:minute bits // ---------------------------------------- if (bufferPosition ==28) { for (int i =21; i <=27; i++) { // count the number of bits with the value '1' dcfP1counter +=DCFbitBuffer[i]; } // perform P1 parity check. Parity is OK if the sum is an EVEN value if ((DCFbitBuffer[28] + dcfP1counter) % 2 ==0) { // Parity1 PASS LED ON digitalWrite(LED_PARITY1PASS, HIGH); // Parity P1 PASS dcfParityCheckP1 =1; } else { // Parity1 FAIL LED ON digitalWrite(LED_PARITY1FAIL, HIGH); // we have no valid data! dcfValidSignal =false; // Turn DCF OK LED OFF digitalWrite(LED_DCFSTATUS, LOW); } } // ---------------------------------------- // Second parity check:hour bits // ---------------------------------------- if (bufferPosition ==35) { for (int i =29; i <=34; i++) { dcfP2counter +=DCFbitBuffer[i]; } // perform P2 parity check. Parity is OK if the sum is an EVEN value if ((DCFbitBuffer[35] + dcfP2counter) % 2 ==0) { // Parity2 PASS LED ON digitalWrite(LED_PARITY2PASS, HIGH); // Parity P2 PASS dcfParityCheckP2 =1; } else { // Parity2 FAIL LED ON digitalWrite(LED_PARITY2FAIL, HIGH); // we have no valid data! dcfValidSignal =false; // Turn DCF OK LED OFF digitalWrite(LED_DCFSTATUS, LOW); } } // ---------------------------------------- // Third parity check:date bits // ---------------------------------------- if (bufferPosition ==58) { for (int i =36; i <=57; i++) { dcfP3counter +=DCFbitBuffer[i]; } // perform P3 parity check. Parity is OK if the sum is an EVEN value (DCFbitBuffer[58] + dcfP3counter) % 2 ==0 ? dcfParityCheckP3 =1 :dcfParityCheckP3 =0; // Turn Parity2 'PASS' or 'FAIL' LED ON if (dcfParityCheckP3 ==1) { // Parity2 PASS LED ON digitalWrite(LED_PARITY3PASS, HIGH); // Parity P3 PASS dcfParityCheckP3 =1; } else { // Parity2 FAIL LED ON digitalWrite(LED_PARITY3FAIL, HIGH); // we have no valid data! dcfValidSignal =false; // Turn DCF OK LED OFF digitalWrite(LED_DCFSTATUS, LOW); } // ---------------------------------------- // finally, check all Parity bits // ---------------------------------------- dcfParityCheckP1 + dcfParityCheckP2 + dcfParityCheckP3 ==3 ? dcfValidSignal =true :dcfValidSignal =false; } //-------------------------------------------------------------------- // before continuing with the next bit, increment counter //-------------------------------------------------------------------- bufferPosition++; //-------------------------------------------------------------------- // check if we have not received too many pulses? //-------------------------------------------------------------------- if (bufferPosition> 59) { // Buffer Overflow ERROR - we have received more pulses before reaching // the 2 second 'gap' signalling the end of the minute. //This error may be due to a noisy signal giving addition peaks/dcfBits // So clear both DCFbit displays and start again. // Reset buffer counter bufferPosition =0; // clear inner LED ring MaximCC.clearDisplay(LedRingInner); // turn Buffer Overflow Error LED ON error(LED_BUFFEROVERFLOW); // exit return; } //-------------------------------------------------------------------- // everything OK so we wait for next incoming DCFbit //--------------------------------------------------------------------}//================================================================================================================//// Function name :finalizeBuffer// called from ://// Purpose :Process the succesfully received DCF data of one minute// Parameters :none// Return value :none////================================================================================================================void finalizeBuffer(void){ //-------------------------------------------------------------------- // We are here because of the detected 2 second 'gap'. // Now check if it correspondends with the buffer counter // 'bufferPosition' which should be value 59 //-------------------------------------------------------------------- if (bufferPosition ==59 &&dcfValidSignal ==true) { // bufferPosition ==59 so turn Buffer Full LED ON digitalWrite(LED_BUFFERFULL, HIGH); // Turn DCF OK LED ON digitalWrite(LED_DCFSTATUS, HIGH); // Reset inner LED ring (incoming time information) MaximCC.clearDisplay(LedRingInner); // copy 'contents' of inner LED ring to the outer LED ring (current time information) for (int i =0; i <59; i++) { MaximCC.setLed(LedRingOuter, i / 8, i % 8, DCFbitBuffer[i]); } // process buffer and extract data sync the time with the RTC decodeBufferContents(); // set Arduino time and after that set RTC time setTime(dcfHour, dcfMinute, 0, dcfDay, dcfMonth, dcfYear); RTC.set(now()); // activate Synced LED digitalWrite(LED_RTCSYNC, HIGH); // Reset running buffer bufferPosition =0; // Reset DCFbitBuffer array, positions 0-58 (=59 bits) for (int i =0; i <59; i++) { DCFbitBuffer[i] =0; } // reset flag MinuteMarkerFlag =false; } // if (bufferPosition ==59) //-------------------------------------------------------------------- // The buffer is not yet filled although the 2 second 'gap' was detected. // Can be result of a noisy signal, starting in middle of receiving data etc. // Turn 'Minute Mark' LED ON //-------------------------------------------------------------------- else { digitalWrite(LED_MINUTEMARKER, HIGH); // Clear displays MaximCC.clearDisplay(LedRingInner); MaximCC.clearDisplay(LedRingOuter); // Reset running buffer and start afresh. Now we are in sync with the incoming data bufferPosition =0; // Reset DCFbitBuffer array, positions 0-58 (=59 bits) for (int i =0; i <59; i++) { DCFbitBuffer[i] =0; } // set flag so we can display incoming pulsed on the inner LED ring. MinuteMarkerFlag =true; }}//================================================================================================================//// Function name :decodeBufferContents// called from ://// Purpose :Evaluates the information stored in the buffer.// This is where the DCF77 signal is decoded to time and date information// Parameters :none// Return value :none////================================================================================================================void decodeBufferContents(void){ // Buffer is full and ready to be decoded dcfMinute =bitDecode(21, 27); dcfHour =bitDecode(29, 34); dcfDay =bitDecode(36, 41); dcfWeekDay =bitDecode(42, 44); dcfMonth =bitDecode(45, 49); dcfYear =bitDecode(50, 57); //call function to calculate day of year and weeknumber dayWeekNumber(dcfYear, dcfMonth, dcfDay, dcfWeekDay); // Get value of Summertime DCFbit. '1' =Summertime, '0' =wintertime dcfDST =bitDecode(17, 17); // determine Leap Year leapYear =calculateLeapYear(dcfYear);}//================================================================================================================//// bitDecode//// called from //================================================================================================================int bitDecode(int bitStart, int bitEnd){ // reset 'bitValue-array' counter int i =0; int value =0;...This file has been truncated, please download it to see its full contents.
Superfilter sketchArduino
//// This is the Superfilter sketch I use with the DCF Analyzer/Clock 2.0 // Udo Klein did an amazing job with this filter//// Erik de Ruiter/* Arduino Uno pin connections I used for the DCF Analyzer Clock DCF input ................. A5 (19) =dcf77_sample_pin Output DCF Filtered ....... 12 =dcf77_filtered_pin Output DCF Semi Synthesized A2 (16) =dcf77_semi_synthesized_pin Output DCF Synthesized .... 6 =dcf77_synthesized_pin LED DCF output filtered ... A4 (18) =dcf77_monitor_pin =DCF Monitor LED LED 1 Hz pulse ............ 10 =dcf77_second_pulse_pin =Filter Locked LED LED DCF OK ................ 13 =dcf77_signal_good_indicator_pin =Signal Quality LED LED Difference Filtered ... 7 =dcf77_filter_diff_pin \ LED Difference Semi Synth.. A0 =dcf77_semi_synthesized_diff_pin -> =Signal Difference LED LED Difference Synthesized 4 =dcf77_synthesized_diff_pin /*/ //// www.blinkenlight.net//// Copyright 2014, 2015 Udo Klein//// This program is free software:you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program. If not, see http://www.gnu.org/licenses/#include /*const uint8_t pon_pin =51; // connect pon to ground !!!const uint8_t data_pin =19;const uint8_t gnd_pin =51;const uint8_t vcc_pin =49;*/const uint8_t dcf77_analog_samples =false;const uint8_t dcf77_analog_sample_pin =5;const uint8_t dcf77_sample_pin =19; // A5const uint8_t dcf77_inverted_samples =0;#if defined(__AVR__)#define ledpin(led) (led)#else#define ledpin(led) (led<14? led:led+(54-14))#endifconst uint8_t dcf77_monitor_pin =ledpin(18); // A4const bool provide_filtered_output =true;const uint8_t dcf77_filtered_pin =ledpin(12);const uint8_t dcf77_inverted_filtered_pin =ledpin(11);const uint8_t dcf77_filter_diff_pin =ledpin(7);const bool provide_semi_synthesized_output =true;const uint8_t dcf77_semi_synthesized_pin =ledpin(16);const uint8_t dcf77_inverted_semi_synthesized_pin =ledpin(15);const uint8_t dcf77_semi_synthesized_diff_pin =ledpin(14);const bool provide_synthesized_output =true;const uint8_t dcf77_synthesized_pin =ledpin(6);const uint8_t dcf77_inverted_synthesized_pin =ledpin(5);const uint8_t dcf77_synthesized_diff_pin =ledpin(4);const uint8_t dcf77_second_pulse_pin =ledpin(10);const uint8_t dcf77_signal_good_indicator_pin =ledpin(13);volatile uint16_t ms_counter =0;volatile Internal::DCF77::tick_t tick =Internal::DCF77::undefined;template void set_output(uint8_t clock_state, uint8_t sampled_d ata, uint8_t synthesized_signal){ if (enable) { const uint8_t filtered_output =clock_state  200) :digitalRead(dcf77_sample_pin)); #else dcf77_inverted_samples ^ digitalRead(dcf77_sample_pin); #endif digitalWrite(dcf77_monitor_pin, sampled_data); digitalWrite(dcf77_second_pulse_pin, ms_counter <500 &&clock_state>=Clock::locked); const uint8_t synthesized_signal =tick ==Internal::DCF77::long_tick ? ms_counter <200:tick ==Internal::DCF77::short_tick ? ms_counter <100:tick ==Internal::DCF77::sync_mark ? 0:// tick ==DCF77::undefined --> default handling // allow signal to pass for the first 200ms of each second (ms_counter <=200 &&sampled_data) || // if the clock has valid time data then undefined ticks // are data bits --> first 100ms of signal must be high ms_counter <100; set_output (clock_state, sampled_data, synthesized_signal); set_output (clock_state, sampled_data, synthesized_signal); set_output (clock_state, sampled_data, synthesized_signal); ms_counter+=(ms_counter <1000); scope_1.process_one_sample(sampled_data); scope_2.process_one_sample(digitalRead(dcf77_synthesized_pin)); return sampled_data;}void output_handler(const Clock::time_t &decoded_time) { // reset ms_counter for 1 Hz ticks ms_counter =0; // status indicator --> always on if signal is good // blink 3s on 1s off if signal is poor // blink 1s on 3s off if signal is very poor // always off if signal is bad const uint8_t clock_state =DCF77_Clock::get_clock_state(); digitalWrite(dcf77_signal_good_indicator_pin, clock_state>=Clock::locked ? 1:clock_state ==Clock::unlocked? (decoded_time.second.digit.lo &0x03) !=0:clock_state ==Clock::free ? (decoded_time.second.digit.lo &0x03) ==0:0); // compute output for signal synthesis Internal::DCF77_Encoder now; now.second =BCD::bcd_to_int(decoded_time.second); now.minute =decoded_time.minute; now.hour =decoded_time.hour; now.weekday =decoded_time.weekday; now.day =decoded_time.day; now.month =decoded_time.month; now.year =decoded_time.year; now.uses_summertime =decoded_time.uses_summertime; now.leap_second_scheduled =decoded_time.leap_second_scheduled; now.timezone_change_scheduled =decoded_time.timezone_change_scheduled; now.undefined_minute_output =false; now.undefined_uses_summertime_output =false; now.undefined_abnormal_transmitter_operation_output =false; now.undefined_timezone_change_scheduled_output =false; now.advance_minute(); tick =now.get_current_signal();}void setup_serial() { Serial.begin(115200);}void output_splash_screen() { Serial.println(); Serial.println(F("DCF77 Superfilter 3.0")); Serial.println(F("(c) 2015 Udo Klein")); Serial.println(F("www.blinkenlight.net")); Serial.println(); Serial.print(F("Sample Pin:")); Serial.println(dcf77_sample_pin); Serial.print(F("Inverted Mode:")); Serial.println(dcf77_inverted_samples); #if defined(__AVR__) Serial.print(F("Analog Mode:")); Serial.println(dcf77_analog_samples); #endif Serial.print(F("Monitor Pin:")); Serial.println(dcf77_monitor_pin); Serial.println(); if (provide_filtered_output) { Serial.println(F("Filtered Output")); Serial.print(F(" Filtered Pin:")); Serial.println(dcf77_filtered_pin); Serial.print(F(" Diff Pin:")); Serial.println(dcf77_filter_diff_pin); Serial.print(F(" Inverse Filtered Pin:")); Serial.println(dcf77_inverted_filtered_pin); Serial.println(); } if (provide_semi_synthesized_output) { Serial.println(F("Semi Synthesized Output")); Serial.print(F(" Filtered Pin:")); Serial.println(dcf77_semi_synthesized_pin); Serial.print(F(" Diff Pin:")); Serial.println(dcf77_semi_synthesized_diff_pin); Serial.print(F(" Inverse Filtered Pin:")); Serial.println(dcf77_inverted_semi_synthesized_pin); Serial.println(); } if (provide_synthesized_output) { Serial.println(F("Synthesized Output")); Serial.print(F(" Filtered Pin:")); Serial.println(dcf77_synthesized_pin); Serial.print(F(" Diff Pin:")); Serial.println(dcf77_synthesized_diff_pin); Serial.print(F(" Inverse Filtered Pin:")); Serial.println(dcf77_inverted_synthesized_pin); Serial.println(); } Serial.print(F("Second Pulse Pin:")); Serial.println(dcf77_second_pulse_pin); Serial.print(F("Signal Good Pin:")); Serial.println(dcf77_signal_good_indicator_pin); Serial.println(); Serial.println(); Serial.println(F("Initializing...")); Serial.println();};void setup_pins() { if (provide_filtered_output) { pinMode(dcf77_filtered_pin, OUTPUT); pinMode(dcf77_filter_diff_pin, OUTPUT); pinMode(dcf77_inverted_filtered_pin, OUTPUT); } if (provide_semi_synthesized_output) { pinMode(dcf77_semi_synthesized_pin, OUTPUT); pinMode(dcf77_semi_synthesized_diff_pin, OUTPUT); pinMode(dcf77_inverted_semi_synthesized_pin, OUTPUT); } if (provide_synthesized_output) { pinMode(dcf77_synthesized_pin, OUTPUT); pinMode(dcf77_synthesized_diff_pin, OUTPUT); pinMode(dcf77_inverted_synthesized_pin, OUTPUT); } pinMode(dcf77_monitor_pin, OUTPUT); pinMode(dcf77_signal_good_indicator_pin, OUTPUT); pinMode(dcf77_second_pulse_pin, OUTPUT); pinMode(dcf77_sample_pin, INPUT); digitalWrite(dcf77_sample_pin, HIGH);}void setup_clock() { DCF77_Clock::setup(); DCF77_Clock::set_input_provider(sample_input_pin); DCF77_Clock::set_output_handler(output_handler);}void setup() { setup_serial(); output_splash_screen(); setup_pins(); setup_clock();/* pinMode(gnd_pin, OUTPUT); digitalWrite(gnd_pin, LOW); pinMode(pon_pin, OUTPUT); digitalWrite(pon_pin, LOW); pinMode(vcc_pin, OUTPUT); digitalWrite(vcc_pin, HIGH); */}void loop() { Clock::time_t now; DCF77_Clock::get_current_time(now); if (now.month.val> 0) { Serial.println(); Serial.print(F("Decoded time:")); DCF77_Clock::print(now); Serial.println(); } Serial.print(DCF77_Clock::get_clock_state()); Serial.print(' '); DCF77_Clock::debug(); scope_1.print(); scope_2.print();}

Kundenspezifische Teile und Gehäuse

This is a PCB I made for the Time and Date displays Maxim_7219_LED_display_unit_for_Adafruit_0_56inch_7_segment_v1_1.zipThis is my PCB design for the very compact smaller 7 segment displays Maxim_7219_LED_display_unit_for_KingBright_7_segment_SC39_11SRWAv1_1.zipTicking sound and Chime sound, see text for explanation Grandfather_Clock_Sound_files.zip

Schaltpläne

DOWNLOAD to view details! dcf77-analyzer-clock-v2_1_jVZT5sqIwn.zip

Herstellungsprozess

  1. Kuckucksuhr
  2. Arduino-Pov-Vision-Uhr
  3. DIY einfachste IV9 Numitron-Uhr mit Arduino
  4. Einfache Wanduhr mit Adafruit 1/4 60 Ring Neopixel
  5. Einfache Wordclock (Arduino)
  6. Arduino-Uhr mit islamischen Gebetszeiten
  7. Arduino Spybot
  8. FlickMote
  9. Hauptuhr
  10. Einfacher Wecker mit DS1302 RTC