• .
  • Willkommen im Forum!
  • Alles beim Alten...
  • Du hast kaum etwas verpasst ;-)
  • Jetzt noch sicherer mit HTTPS
Hallo, Gast! Anmelden Registrieren


TN Tochteruhr - back to life
#1
Meine bessere Hälfte hat angewiesen, dass wir eine grosse Uhr brauchen  klappe  Heart .

Also nutze ich die Gelegenheit, eine olle Tochteruhr von TN aus dem Bastelkeller zu holen... Tochteruhren laufen ohne ihre Mutter leider nicht, da sie nur ein sehr primitives (und langlebiges) Schrittmotorwerk haben. Alle Minute braucht es einen 12V-Puls von etwa 0,4s Länge. Die Spule des Werkes muss bei jedem Impuls umgepolt werden, sonst läuft da nix.

Aktueller Status: Spannungsversorgung mit einem alten 12V Netbooknetzteil, die Ansteuerungsschaltung mit Mosfets und Minirelais steht.
Auf dem Steckbrett  klappe  Big Grin

   

Bei der Gelegenheit probiere ich ein interessantes µC-Board aus - Adafruit Feather. Es basiert auf dem ATMega 32u4 und hat ein paar Features, die es für das Projekt geeignet machen:
  • Es hat einen Anschluss für Lithiumakkus und die Ladeelektronik an Bord. Bei Stromausfällen kann es also wenigstens die fehlenden Minuten protokollieren (und später nachholen)
  • Arduinoprogrammierung
  • Platz für zusätzliche Hardware. In diesem Fall ein Spannungswandler 12V->5V und 2 Mosfets, die den digitalen Output von 3,3V auf 5V bringen
   

Fehlt noch die Anbindung einer genauen RTC und ein wenig Programmierung.
 
Reply
#2
Kannst du die 12V nicht auch noch aus dem Akku knautschen? Zeit per GPS, DCF?
 
Reply
#3
Wenn ich auf 12V aus der Batterie umstellen würde, wäre die Laufzeit sehr kurz (12V/20mA, 0,4s jede Minute). Netzbetrieb mit Backupbatterie erscheint mir da sinnvoller. Die 5V müsste ich auch generieren, da die Relais bei 3,7V nicht ziehen.

Zu GPS/DCF: Tochteruhren haben grundsätzlich keine Möglichkeit, die Zeigerstellung zu detektieren. Die Elektronik weiss also nicht, was aktuell angezeigt wird. Insofern kommt es mir auch nicht darauf an, die Zeit aus DCF oder GPS zu gewinnen und anzuzeigen. Wichtig ist nur der genaue und zuverlässige Takt. Ich hab gute Erfahrungen mit dieser RTC gemacht: DS3231. Ein altes Projekt (LED-Uhr mit Stunden- und Minutenanzeige) läuft seit mehreren Jahren ohne Korrektur und geht keine Minute falsch  Confused .
Mein Vorteil: RTC ist da, Programmierung dafür auch fast (für's Teensy-Board, braucht kleine Anpassungen).
 
Reply
#4
Du kannst ja auf der Zeigerrückseite einem kleinen Magneten befestigen und per Hallsensor hinter dem Blatt messen.. Smile
 
Reply
#5
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:
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...  Rolleyes
 
Reply
#6
Alles will nicht so, wie es soll  misstrau .
Abstürze des µC, falsche Zählung der Sekunden... hat gedauert bis zur Erleuchtung. Es ist halt Mist, die Spule eines Schrittmotors mit der gleichen Betriebsspannung zu schalten, an der der Prozessor hängt. Kräftige (negative) Spannungspeaks bringen alles aus dem Takt.

220nF Kondensator über Spule hilft hoffentlich...

Jetzt kann die (zugegeben) schlechte Programmierung komplett umgekrempelt werden. Die sieht nämlich nur so aus, weil ich dauernd mit den Symptomen der Peaks zu kämpfen hatte.
 
Reply
#7
hardware meets software Big Grin
...mit der Lizenz zum Löten!
 
Reply
#8
Freilaufdiode braucht's nicht?
 
Reply
#9
Doch. Aber wie polen, wenn die Spule in zwei Richtungen durchflossen wird?

Die Motorspule hat 32H und hängt im Abschaltmoment kurz in der Luft. Ich probiere gerade an beiden Enden Kondensatoren nach Masse, damit der Strom igendwohin fliessen kann. Scheint zu funktionieren.

Wird sich nach einer Weile Probelauf zeigen...
 
Reply
#10
übliche Lösung: zwei Zenerdioden, in Serie+verpolt , mit Nennspannung ; also bei 12V eben 2 x 12V-Typen;
oder passender Überspannungsableiter (wird in Industrie-Relais / Schaltschrankbau oft verwendet)

Kondensatoren sind eher problematisch: damit produziert man auch Stoss-ströme beim Einschalten, was zb Relais gar nicht mögen (Lebensdauer...oder sogar Kontakt-verklebt....alles schon gehabt Rolleyes  )
    Don't worry about getting older.  You're still gonna do dump stuff...only slower
 
Reply
#11
Oder nen ollen H-Brücken-Motortreiber.
 
Reply
#12
(17.11.2018, 10:03 PM)alfsch schrieb: übliche Lösung: zwei Zenerdioden, in Serie+verpolt , mit Nennspannung ; also bei 12V eben 2 x 12V-Typen;
oder passender Überspannungsableiter (wird in Industrie-Relais / Schaltschrankbau oft verwendet)

Kondensatoren sind eher problematisch: damit produziert man auch Stoss-ströme beim Einschalten, was zb Relais gar nicht mögen (Lebensdauer...oder sogar Kontakt-verklebt....alles schon gehabt Rolleyes  )

Ich hab Z-Dioden für 180V, 130V, 68V... aber keine 12V motz . Ich behelfe mich erstmal mit kleinen Kondensatoren nach Masse, die in den 2..3ms des Schaltvorgangs den Spulenstrom abnehmen. Und setze die Z-Dioden auf die Einkaufsliste.

Nun prellt und zuckt vorerst nix mehr, aber es gab Verluste... Ein Pin des µC ist tot, es hat auch mal geraucht (ist aber noch etwas Rauch dringeblieben - ich war schnell  Weih ).

Neue Software gibt es auch, meiner Meinung nach eleganter und richtiger  klappe  Cool
Code:
// 2018-11-18: TN-Tochteruhr mit hochgenauer RTC
// Version 2.00
// 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>

byte led = 13;                   // interne LED an Pin 13
byte TN1 = 6;                    // Ausgang 1 an Pin 6
byte TN2 = 15;                   // Ausgang 2 an Pin 15
byte power = 11;                 // Pin 11 ist der Sensor für die externe Spannungsversorgung
byte SQW = 1;                    // 1Hz Rechteck-Signal von RTC an Pin 1
byte SQWstatus = 0;              // 1Hz Rechteck-Signal von RTC an Pin 0
byte SetPin = 14;                // an Pin 14 kann die Uhr gestellt werden
volatile int minutes = 0;        // Zähler m
volatile byte seconds = 0;       // Zähler s
volatile bool TotzeitFlag = true;// Nomen est omen
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(SQWstatus, INPUT);
 pinMode(SetPin, INPUT_PULLUP);
 
 digitalWrite(TN1, LOW);        // Beide Spulenenden auf Masse
 digitalWrite(TN2, LOW);
 
 attachInterrupt(3, Hz_interrupt,CHANGE); // Interrupt 3 an Pin 1 aktivieren
}

void loop() {
 if (digitalRead(power) == HIGH && TotzeitFlag == false) {
   if (minutes > 0) {           // Minutenstack wird abgearbeitet
     if (coilstatus == LOW) {   // die Spule muss wechselseitig bestromt werden
       digitalWrite(TN1, HIGH); // Anschluss 1 bekommt 12V
       coilstatus = HIGH;       // das nächstemal vom anderen Spulenende...
     }                          
     else {                     // das andere Ende
       digitalWrite(TN2, HIGH);
       coilstatus = LOW;
     }
     minutes--;                 // Minutenstack verkleinern
     TotzeitFlag = true;        // Atempause für die Uhrmechanik
   }
 }
 if (digitalRead(SQWstatus) == LOW) {  // 0,5s Atempause für die Uhrmechanik
   digitalWrite(TN1, LOW);
   digitalWrite(TN2, LOW);
 }
}

void Hz_interrupt()
{
 if (digitalRead(SQWstatus) == HIGH) {
   seconds++;                   // schon wieder eine Sekunde im Stack
   if (seconds == 60) {
     seconds = 0;
     minutes++;                 // der Minutenstack...
     if (minutes >= 720) minutes = 0; // nach 12h ohne externe Spannungsversorgung
   }
   if (digitalRead(SetPin) == LOW) {
     minutes++;                 // der Minutenstack wird per Hand erhöht (Uhr stellen)
     seconds = 0;
   }
   digitalWrite(led, HIGH);     // Funktionsindikator LED im 1s-Takt
   TotzeitFlag = false;         // bereit für neuen Schaltvorgang
 }
 else {
   digitalWrite(led, LOW);      // Funktionsindikator LED im 1s-Takt
   TotzeitFlag = true;          // 0,5s Pause
 }
}
 
Reply
#13
Vielleicht geht es auch mit 2 normalen Dioden.

Simu ohne Dioden (Die Relais schalten wechselseitig zwischen 12V und Masse hin- und her, Totzeit 3ms):
   

Mit Dioden:
   

Die Ströme werden durch die Spule selbst begrenzt.
Gleich mal probieren...

--
Geht, keine Störungen mehr und die Relais sind hoffentlich auch zufrieden.
 
Reply
#14
Um die Relais umgehen zu können, könntest du dir vielleicht für 1-2€ ein "Standard"-Modul mit L298N ansehen.
Auf denen sind die Dioden gegen GND und nach oben gegen 12V auch schon integriert...dann ists auch nicht mehr wichtig in welcher Reihenfolge die Schalter geöffnet/geschlossen werden.
 
Reply
#15
kahlo, die Sache geht auch mit Dioden - klar. 
du solltest dann aber 4 nehmen, 2 nach Masse (haste schon) + 2 nach "+12V" . (dann fangen die auch die Spannungsw-spitze ab...). dann is perfekt. Wink 
(wie mit ZD , nur die Entladung geht halt in die Versorgung; mit ZD wird sie in den Z-dioden "verbraten" , was die restliche Schaltung eben sicher nicht beeinflussen kann.)

ed: oder eben ohne Relais, gleich "direkt" schalten, mit sowas , zb :
https://de.aliexpress.com/item/Special-p...54491.html

[Bild: HTB1urRbilyWBuNkSmFPq6xguVXaB.jpg]
    Don't worry about getting older.  You're still gonna do dump stuff...only slower
 
Reply
#16
(18.11.2018, 07:40 PM)E_Tobi schrieb: Um die Relais umgehen zu können, könntest du dir vielleicht für 1-2€ ein "Standard"-Modul mit L298N ansehen.
Auf denen sind die Dioden gegen GND und nach oben gegen 12V auch schon integriert...dann ists auch nicht mehr wichtig in welcher Reihenfolge die Schalter geöffnet/geschlossen werden.
Die sehen gut aus!

Andererseits sollen die Relais 100M mechanische Schaltvorgänge aushalten... und nur 200k elektrische Schaltvorgänge. Was die damit nur gemeint haben. Die eine Zahl zu gross (reicht 95 Jahre), die andere zu klein (reicht keine 3 Monate). https://no.mouser.com/datasheet/2/307/g6...189828.pdf

@Alfsch: Die Spule wird immer kalt (komplett stromlos) an die 12V gebracht, insofern müssten die 2 Dioden reichen. Denke ich  misstrau . Das Guckitraining verbietet überflüssige Teile  lachend .
 
Reply
#17
naja - du brauchst "nur" die mechanischen Limits, weil die Kontakte ja kaum beansprucht werden (weg-brennen -> Lebenszeit verkürtzt ! )

+
wenn die Uhr auch mit 10V - Impuls zurecht kommt, kannst sogar so mini-Treiber nehmen:  (für 33 ct Rolleyes  )
https://de.aliexpress.com/item/2-channel...17929.html

[Bild: HTB1oA5.MpXXXXajXXXXq6xXFXXXN.jpg]

(18.11.2018, 09:11 PM)kahlo schrieb: @Alfsch: Die Spule wird immer kalt (komplett stromlos) an die 12V gebracht, insofern müssten die 2 Dioden reichen. Denke ich  misstrau . Das Guckitraining verbietet überflüssige Teile  lachend .

jaaa - aber: das ABschalten ist das Problem... !!   zum einschalten braucht es gar keinen "Schutz" - wenn du nie mehr abschaltest.
dann knallt die gespeicherte Energie der Spule ....irgenwo hin. DAS ist das Problem.
und da helfen nur 2x ZD  oder 4 x D  "wirklich korrekt". weiter gibts nichts "einzusparen" . Tongue
    Don't worry about getting older.  You're still gonna do dump stuff...only slower
 
Reply
#18
Mmh... misstrau  Die Simulation gibt nur einen negativen Peak beim Abschalten. Ein Kontakt der Spule ist permanent auf Masse, der andere wird von 12V auf Masse geschaltet (mit 3ms in der undefinierten Luft) - dieser Kontakt sieht den negativen Peak, wenn keine Diode dran ist.

10V reichen leider nicht, über 11 müssen es sein.
 
Reply
#19
ah, eine Seite auf Masse... Rolleyes 
ja, dann sind die 2 D  perfekt. genug. Wink
    Don't worry about getting older.  You're still gonna do dump stuff...only slower
 
Reply
#20
Die Kontakte sind natürlich abwechselnd permanent auf Masse  lachend  lachend  Weih . Sie werden nie gleichzeitig geschaltet.

--
Inzwischen läuft es stabil und hat noch keine Sekunde verloren/gewonnen. Die verwundete Hardware tut es also. Die Software muss noch mit dem einen oder anderen Stromausfall getestet werden. Aber ich bin stolz darauf, alles ohne den "delay"-Befehl hinbekommen zu haben  Tongue .
 
Reply