PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Steuerung für TN Tochteruhr



128er
11.12.2013, 19:33
Guten Abend!

Ich habe schon vor längerem eine alte Tochteruhr von Telefonbau Normalzeit vor dem Schrott gerettet. Anschließend habe ich mir eine kleine Ansteuerung mit einer H-brücke gebaut. Attiny dazu und fertig (dachte ich mir so :) )

Allerdings stoße ich nun an meine Grenzen was die Genauigkeit angeht. Nach 15 Stunden Betrieb, habe ich eine Abweichung von ca. 3 Minuten. Mit welchen Mitteln könnte man das noch weiter ausreizen? Ein DCF77 Empfänger wäre natürlich eine Möglichkeit. Würde ein 32 kHz Uhrenquarz auch einen vebesserten Effekt herbeiführen? Oder Verbesserungen am Code? Oder enger tollerierter Quarz? :confused:

Hier ist mein Programm in Bascom Basic:



$regfile = "attiny45.dat"

'### 2 MHz Quarz, Fusebit für 1/8 Systemtakt gesetzt ###
$crystal = 250000
$hwstack = 36
$swstack = 4
$framesize = 4


'### Bit zum minütlichen Wechsel des Ausgangsports ###
Dim B As Bit


'### Zählvariable wird beim Timerüberlauf inkrementiert ###
Dim C As Word


'### Ausgänge für beide Brückenzweige ###
Config Portb.0 = Output
Config Portb.1 = Output



'### Timer0 konfigurieren. 0,25 MHz (Systemtakt) / 64 (Prescaler) = 3906,25 / 256 (8-Bit Timer) * 60 (Sekunden) = 915,527 ###

Config Timer0 = Timer , Prescale = 64



'### Timerüberlauf ###
On Ovf0 On_ovf0
Enable Ovf0


Enable Interrupts

Start Timer0


C = 0


Do

If C = 915 Then Hier evtl. die tatsächlichen 915,527 benutzen? Inklusive passendem Datentyp für Kommazahlen?

C = 0

Toggle B



If B = 0 Then

Portb.1 = 1

Waitms 400

Portb.1 = 0

Else

Portb.0 = 1

Waitms 400

Portb.0 = 0

End If

End If

Loop

End



'### Routine bei Timerüberlauf ###
On_ovf0:
Incr C
Return





Hier ist der Schaltplan. Das Tiny13 bitte ignorieren. Es ist ein Tiny45. Auch von den Pinbezeichnungen her. Habs nur nicht hinbekommen auch den Namen zu ändern :rolleyes:
Der Quarz ist ein 2 MHz Wald und Wiesen Typ von Conrad. Die Schaltung läuft wegen der Uhr auf 6 Volt. Die Stromaufnahme liegt bei ca. 520 µA zwischen den Minutenimpulsen. Und um die 23 mA beim Minutenimpuls (ca. 400 ms lang).
26900


Danke fürs anschauen und helfen! :)


Gruß 128er

P.S.:
Da es ein Mischmasch aus Code und Hardware ist, habe ich es einfach mal in Elektronik eingestellt. Sollte ein Mod das anders sehen, bitte verschieben. :rolleyes:

Hubert.G
11.12.2013, 20:32
Helfen würde nur ein 32kHz Quarz oder zumindest ein Baudratenquarz. Eine Temperaturregelung (Quarzheizung) dazu würde die Genauigkeit auch drastisch erhöhen.
Wie du die Schaltung aufgebaut hast weiß ich nicht, aber zum µC hin solltest du in die VCC eine Diode geben und einen kleinen Elko, etwa 10µ und einen 100n Kondensator.
10k vom Reset nach VCC.

Peter(TOO)
11.12.2013, 20:37
Hallo 128er,

915,527 kannst du nicht verwenden!
C wird bei jedem Interrupt um 1 erhöht.

Du könntest aber, abhängig von B, einmal mit 915 und einmal mit 916 vergleichen, das gäbe dann im Mittel 915.5

Oder du legst die Vergleichswerte in einer Tabelle ab.
z.B. 3x 915 und 5x 916
Sind jetzt nur geratenen Werte, ich bin gerade zu faul zum Rechnen.

MfG Peter(TOO)

128er
11.12.2013, 21:03
Danke schonmal für die Hinweise!

@Hubert
Ein beheizter Quarz würde natürlich schon an Raketenwssenschaft grenzen :D . Die Stromaufnahme wird allerdings ein Problem sein, da die Uhr über Batterie betrieben werden soll.

Reset und alle übrigen Pinne hab ich erstmal vernachlässigt. Der Plan ist noch nicht der Weisheit letzter Schluss. Evtl. führ ich hinterher alle Pins ordentlich raus für mögliche Erweiterungen. Werde mir deine Hinweise aber zu Herzen nehmen.

@Peter
Den Vorschlag mit der Abhängigkeit von B die Werte zu ändern find ich sehr gut. Werd ich gleich mal ausprobieren! Das Problem der falschen Zeit tritt nämlich bei beiden Werten auf. Dann sollte das Mittel ja (theoretisch) optimal sein. Beim Arbeiten mit Tabellen müsst ich als Gelegenheitsprogrammierer erstmal bei 0 anfangen.


Gruß 128er

Peter(TOO)
11.12.2013, 22:23
Hallo, Kannst du auch so lösen:



Dim D As Word

...

D = 0
Do
If D = 0 And C = 915 Then
C = 999
Incr D
Else If D = 1 And C = 916 Then
C = 999
Incr D
Else If D = 2 And C = 916 Then
C = 999
Incr D
Else If D = 3 And C = 916 Then
C = 999
D = 0
End If

If C > 990 Then
C = 0

Toggle B



If B = 0 Then

Portb.1 = 1

Waitms 400

Portb.1 = 0

Else

Portb.0 = 1

Waitms 400

Portb.0 = 0

End If

End If

Loop



Kannst du beliebig ausbauen.
Ich kenn dein BASIC nicht, müsste aber auch ein Switch haben, geht auch an Stelle der verschachteltet If's

MfG Peter(TOO)
P.S. BASIC ist bei mir schon ewig her ....

wkrug
12.12.2013, 10:24
Die Lösung könnte ein RTC Chip sein.
Bei Dallas gibt es welche, die eine Abweichung von 3 Sekunden pro Jahr haben.
Deine Uhr läuft dann mit dem normalen Quarz und jede Minute / Stunde wird der RTC Chip einmal ausgelesen und der Controller aktualisiert.
Der Stromverbrauch sollte dann auch nicht das Problem sein.
Zudem hat der RTC Chip eine eigene externe Stützbatterie, falls Du die Batterie der Uhr doch mal wechseln musst.

DCF 77 ist auch ne Lösung, braucht aber mehr Strom.
Ich hab das mal so gemacht, das die Controller Uhr 3 mal eine gültige Uhrzeit vom DCF77 kriegen muss, damit sie für die Tochteruhr übernommen wird.
Bei jedem 30igstem Sekundenimpuls wird die interne Controlleruhr wieder auf 30 Sekunden gestellt.
Damit vermeidet man dann einen Gangfehler von max 1:59 Minuten.
Die Konfiguration läuft bei mir seit etwa 2 Jahren problemlos.
Sommer und Winterzeit stellt sich auch automatisch um, so lange ein DCF Signal vorhanden ist.

Die Soft ist in "C" also nicht mit BASCOM kompatibel.

128er
12.12.2013, 15:16
Hallo zusammen!

Gestern Abend habe ich den Code nochmal geändert, so dass jede Minute gewechselt wird zwischen C = 915 oder 916. Da mittelt sich aber garnichts. Wird eher schlimmer :D . Nach 17 Stunden Betrieb, gibts nen Gangfehler von 7 Minuten (nachgehend).

Werd mir nochmal alle Möglichkeiten anschauen. Die idee mit der Realtimeclock ist auch gut.

Peter(TOO)
12.12.2013, 17:14
Hallo,

Dann hat sich der Fehle verdoppelt, dann musst du 914 und 915 nehmen.

Die genaue Rechnerei habe ich mir erspart, ging nur ums Prinzip, wie man nicht ganzzahlige Teiler machen kann.

MfG Peter(TOO)

128er
16.12.2013, 15:05
Kurze Aktualisierung...

Nach 15 Stunden hab ich es auf 1 Minute und 5 Sekunden Gangfehler geschafft.

Die Variable D wurde hinzugefügt, um jede Minute einen anderen Zählwert einzusetzen. Ist mit sicherheit keine elegante Methode. Vorallem kann ich mir vorstellen das es besser wäre, schon innerhalb einer Minute zu mitteln. Und das ganze nicht über mehrere Minuten zu ziehen. Warscheinlich hätte man mit etwas Mathematikverständnis den richtigen Mittelwert auch direkt errechnen können. Da ich ein sollches Verständnis nicht besitze, lief es über try and error :rolleyes:

Hier ist der aktuelle Code:




$regfile = "attiny45.dat"

'### 2 MHz Quarz, Fusebit für 1/8 Systemtakt gesetzt ###
$crystal = 250000
$hwstack = 36
$swstack = 4
$framesize = 4


'### Bit zum minütlichen Wechsel des Ausgangsports ###
Dim B As Bit


'### Zählvariable wird beim Timerüberlauf inkrementiert ###
Dim C As Word


'### Zählkonstante für Mittelung
Dim K As Word



Dim D As Byte


'### Ausgänge für beide Brückenzweige ###
Config Portb.0 = Output
Config Portb.1 = Output




'### Timer0 konfigurieren. 0,25 MHz (Systemtakt) / 64 (Prescaler) = 3906,25 / 256 (8-Bit Timer) * 60 (Sekunden) = 915,527 ###

Config Timer0 = Timer , Prescale = 64



'### Timerüberlauf ###
On Ovf0 On_ovf0
Enable Ovf0


Enable Interrupts

Start Timer0


C = 0
D = 0

Do




Select Case D

Case 0 : K = 915
Case 1 : K = 916
Case 2 : K = 915
Case 3 : K = 915
Case 4 : K = 916
Case 5 : K = 916
Case 6 : K = 916
Case 7 : K = 916
Case 8 : K = 915

End Select

If D = 8 Then

D = 0

End If

Incr D







If C = K Then

C = 0

Toggle B



If B = 0 Then

Portb.1 = 1

Waitms 400

Portb.1 = 0

Else

Portb.0 = 1

Waitms 400

Portb.0 = 0

End If

End If







Loop

End



'### Routine bei Timerüberlauf ###
On_ovf0:

Incr C


Return

Peter(TOO)
16.12.2013, 17:02
Hallo,

Das
incr D
ist so falsch !

Dein Do ... Loop wird tausende male pro Sekunde durchlaufen, nicht nur dann wenn C incrementiert wurde !!



[...]


C = 0
D = 0
K = 915

Enable Interrupts
Start Timer0

Do

Select Case D
Case 0 : K = 915
Case 1 : K = 916
Case 2 : K = 915
Case 3 : K = 915
Case 4 : K = 916
Case 5 : K = 916
Case 6 : K = 916
Case 7 : K = 916
Case 8 : K = 915
End Select

If C >= K Then
C = 0
Incr D
If D > 8 Then
D = 0
End If

Toggle B
[...]


1. Da C im Interrupt incrementiert wird, solltest du C initialisieren, bevor du den Timer startest.
2. Bei solchen Zählern sollt man immer auf grösser als oder grösser gleich abfragen ( If D > 8 Then).
Falls D irgendwie einen Wert ausserhalb von 0 bis 8 annimmt, läuft deine Schlaufe sonst über 65'000 mal durch, D ist Word, also 16 Bit, bis D endlich auf 0 gesetzt wird!



MfG Peter(TOO)