Heute hab ich die RTC verdrahtet und das Programm geschrieben...
Der abenteuerliche Drahtverhau sieht nun so aus (wird hoffentlich besser auf Lochraster):
Und das Programm dazu:
Die Uhr lässt sich nun mit einem Taster stellen. Bei Stromausfall zählt sie die Minuten, die sie aufholen muss. Falls es länger dauert als 12h, ist sie so schlau, die 12h einzusparen ;-)
Nun kommt meine grosse Schwäche: das hübsch machen, wenn's doch schon geht...
Der abenteuerliche Drahtverhau sieht nun so aus (wird hoffentlich besser auf Lochraster):
Und das Programm dazu:
Code:
// 2018-11-16: TN-Tochteruhr mit hochgenauer RTC
// Version 1.0
// von kahlo (kahlo@stromrichter.org)
// Hardware: Adafruit Feather ( https://www.adafruit.com/product/2771 )
// Hardware: Adafruit DS3231 Precision RTC ( https://www.adafruit.com/product/3013 )
// Hardware: TN Tochteruhr, Bahnhofsuhr
// Hardware: 2 Relais 5V, 1xUM, 2 NMOS, Widerstände, LM7805
// Programmierumgebung: Arduino ( http://arduino.cc/ )
#include <Wire.h>
int led = 13; // interne LED an Pin 13
int TN1 = 6; // Ausgang 1 an Pin 6
int TN2 = 15; // Ausgang 2 an Pin 15
int power = 11; // Pin 11 ist der Sensor für die externe Spannungsversorgung
int SQW = 1; // 1Hz Rechteck-Signal von RTC an Pin 1
int SetPin = 0; // an Pin 0 kann die Uhr gestellt werden
volatile bool SecondFlag = false; // ISR Sekundenmarker
int seconds = 0; // Zähler s
int minutes = 0; // Zähler m
bool coilstatus = LOW; // Polaritätsstatus der Uhrwerkes bzw. der Spule
void setup() {
Wire.begin(); // Initialisierung der RTC
Wire.beginTransmission(104);// DS3231 Adresse
Wire.write(0x0E); // Registerauswahl
Wire.write(0b01000000); // Registerbitmap, schaltet das 1Hz-Rechteck ein (siehe DB vom DS3231)
Wire.endTransmission();
pinMode(led, OUTPUT); // Definition der Pins
pinMode(TN1, OUTPUT);
pinMode(TN2, OUTPUT);
pinMode(power, INPUT);
pinMode(SQW, INPUT_PULLUP);
pinMode(SetPin, INPUT_PULLUP);
digitalWrite(TN1, LOW); // Beide Spulenenden auf Masse
digitalWrite(TN2, LOW);
attachInterrupt(3, Hz_interrupt, FALLING); // Interrupt 3 an Pin 1 aktivieren
}
void loop() {
if (digitalRead(SetPin) == LOW) { // Stellen der Uhr per Hand - Pin mit Masse verbinden (Taster)
minutes++; // einfach den Minutenstack erhöhen...
seconds = 0; // auch noch sekundengenau kann es sein ;-)
}
if (SecondFlag == true) { // Die ISR setzt den Flag, wenn 1s um ist
delay(50); // falls was prellt (schlechte Verkabelung)
seconds++; // der Sekundenstack...
if (seconds == 60) {
seconds = 0;
minutes++; // der Minutenstack...
}
if (minutes >= 720) minutes = 0; // nach 12h ohne externe Spannungsversorgung
if (digitalRead(led) == LOW) digitalWrite(led, HIGH); // Funktionsindikator
else digitalWrite(led, LOW); // LED im 2s-Takt
SecondFlag = false; // Reset Flag
}
if (digitalRead(power) == HIGH) { // Wenn externe Spannung da ist, läuft die Uhr
if (minutes > 0) { // Minutenstack wird abgearbeitet
if (coilstatus == LOW) { // die Spule muss wechselseitig bestromt werden
digitalWrite(TN1, HIGH); // Anschluss 1 bekommt 12V
delay(400); // so lange braucht die Uhr zum Zeigerbewegen
digitalWrite(TN1, LOW); // Anschluss 1 auf Masse
coilstatus = HIGH; // das nächstemal vom anderen Spulenende...
}
else { // das andere Ende
digitalWrite(TN2, HIGH);
delay(400);
digitalWrite(TN2, LOW);
coilstatus = LOW;
}
minutes--; // Minutenstack verkleinern
delay(500); // Atempause für die Uhrmechanik
}
}
}
void Hz_interrupt()
{
SecondFlag = true; // schon wieder eine Sekunde im Stack
}
Die Uhr lässt sich nun mit einem Taster stellen. Bei Stromausfall zählt sie die Minuten, die sie aufholen muss. Falls es länger dauert als 12h, ist sie so schlau, die 12h einzusparen ;-)
Nun kommt meine grosse Schwäche: das hübsch machen, wenn's doch schon geht...