Forum: Mikrocontroller und Digitale Elektronik Binäruhr mit Spannungsüberwachung (ATmega8)


von Daniel B. (daniel80)


Angehängte Dateien:

Lesenswert?

Hallo alle zusammen,

ich möchte in diesem Beitrag meine Version einer Binäruhr vorstellen.
Ja ja, ich höre schon einige Stimmen die sagen "schon wieder so'n Ding".
Aber trotzdem möchte ich gerne Feedback zu diesem Projekt haben.

Die Hardware ist ziemlich einfach gehalten, ich benutze einen Atmel 
ATmega8,
18 rote low-current LEDs und einen einzelnen Taster zur Eingabe.

Die LEDs werden per Multiplex angesteuert, dazu wird die aktuelle Wert 
von
Sekunden/Minute/Stunde an einen Port gelegt und die jeweilige "Zeile"
(also s/m/h) auf Masse gelegt. Die Uhr verwendet pro Zeile 6 LEDs, die 
6. LED
in der Stundenzeile wird zur Statusanzeige benutzt.

Da ich die Uhr mit einem Satz Akkus betreibe habe ich zusätzlich eine
Überwachung der Spannungsversorgung eingebaut. Diese soll eine schwache
Versorgungsspannung anzeigen, bevor die Brown-Out Erkennung zuschlägt. 
Für
die Spannungsüberwachung verwende ich den eingebauten Komparator mit der
eingebauten Referenzspannung. Die Versorgungsspannung wird über einen
Spannungsteiler an den Eingangsport gelegt, bei etwa 7,3V fängt die 
Status-LED
an zu blinken. Die Überwachung der Spannung wird zu Beginn einer Minute
durchgeführt.
Um Strom zu sparen wird der Controller in der Idlezeit in einen 
Powerdown-Modus
geschaltet, dieser wird durch den Timerinterrupt dann wieder verlassen.
Im aktuellen Design wird die Versorgungsspannung die ganze Zeit über an 
den
Spannungsteiler gelegt. Ich arbeite aber an einer Lösung um die Spannung 
nur
anzulegen wenn sie auch gemessen werden soll.

Um der Uhr ein einfaches und klares Design zu geben habe ich nur einen 
Taster
vorgesehen. Es werden jeweils kurze und lange Tastendrücke erkannt, 
damit
manövriert man durch das Einstellungsmenü:
- Dimmer an/aus
- Einstellen der Minuten
- Einstellen der Stunden
- Einstellen der Alarmminuten
- Einstellen der Alarmstunden
Wenn durch einen langen Tastendruck zum nächsten Menüpunkt geschaltet 
wird
blinkt die Status-LED kurz auf.

Neben der frei wählbaren Alarmzeit ist auch eine (beinahe) beliebige 
Anzahl
an Alarmzeiten im Flash vorgesehen. Ein Alarm wird durch Blinken der Uhr
angezeigt.

Und nun komme ich zu dem Teil, zu dem ich die meisten Kommentare 
erwarte: ich
benutze den internen Oszillator mit 1MHz Taktrate. Damit eine Sekunde 
auch eine
Sekunde ist benutze ich einen Softwareteiler zusätzlich zum Teiler des 
Hardware-
timers. Meine Begründung für diese Entscheidung ist relativ einfach: ich 
möchte
mit dieser Uhr weder Industrie- noch Automotive- noch 
Militäranforderungen
erfüllen. Das soll heißen, dass ich die Uhr nur in geschlossenen Räumen 
bei
Temperaturen zwischen 18°C und 30°C betreiben will. Nach mehreren 
Versuchen
kann ich sagen, dass die Abweichung der Uhr erst dann zu groß wird wenn 
auch
der Akku leer ist.
Die Abstimmung wird am einfachsten mit einem Oszilloskop durchgeführt, 
dazu
wird in der Software ein Debugpin aktiviert, der mit jeder Sekunge 
toggelt.
Über den Softwareprescaler wird das Feintuning vorgenommen.

Um zeitabhängig Funktionen auszuführen sie die Software sogenannte 
Hookfunktionen
vor, damit kann jeweils vor und nach der Berechnung von s/m/h eine 
Funktion
ausgeführt werden.

Die Software wird auf zwei Dateien aufgeteilt, zum einen die eigentliche
Impementierung der Uhr (binclock.c), zum anderen die Parameter zur 
individuellen
Steuerung (settings.h). Im Header werden die folgenden Einstellungen 
durchgeführt:
- die festen Alarmzeiten
- Dauer des Blinkens zur Alarmanzeige
- Initialzustand des Dimmers
- Entprellzeit zur Tastendruckerkennung
- Softwareteiler für die Feinabstimmung der Uhr
- Aus-/Einschalten des Debugpins zur Messung der Sekundenzeit


Zu guter Letzt noch eine Zusammenfassung der Features:
- Binäruhr auf Basis eines Atmel ATmega8
- Nutzung des internen Oszillators mit 1MHs
- Betrieb mit 9V Akku
- 18 rote low-current LEDs, Multipleansteuerun
- ein Taster zur Steuerung
- Eingabe einer variablen Alarmzeit
- beliebig viele feste Alarmzeiten
- Alarmanzeige durch Blinken
- Überwachung der Versorgungsspannung
- Hookfunktionen zur zeitabhängigen Funktionssteuerung
- Powerdown des Prozessors während der Idlezeit


Was noch geplant ist:
- Ablage der festen Alarmzeiten im EEPROM
- Ablage der Blinkdauer für den Alarm im EEPROM
- Ablage des Dimmerzustands im EEPROM
- Ablage der Tastenentprellungszeit im EEPROM
- Ablage des Softwareteilers im EEPROM
- Ablage des Debugzustandes im EEPROM
- Aktivierung der UART zur Steuerung der Uhr
- An-/Ausschalten des Spannungsteilers zur Spannungsmessung

Im Anhang zu diesem Beitrag finden sich die Sourcen, der Schaltplan und
ein Foto, so bekommt ihr einen ersten Eindruck.


Ich hoffe auf zahlreiches Feedback von euch und nehme gerne Ideen
in die TODO-Liste auf.


Viele Grüße,
Daniel

von Uwe (de0508)


Lesenswert?

hallo,

bei isr-routinen sollte man darauf achten veränderliche variable als 
volatile type name; zu deklariren. Läuft den Programm ohne sauber?

Ich mache diese Define so:
1
#define TURE (1==1)
2
#define FALSE !TRUE

siehst Du den Vorteil?

Man kann dem Kompiler helfen und einge Funktionen zusätzlich noch als 
static anstatt inline deklarieren, dann kann er besser optimieren.

von Jonas Quinn (Gast)


Lesenswert?

Wieder ein Beispiel für "Warum sollte mans einfach machen, wenn es auch 
komplizierter geht"...

von Peter R. (peterfido)


Lesenswert?

Uwe S. schrieb:
> Ich mache diese Define so:#define TURE (1==1)
> #define FALSE !TRUE

TURE sollte bestimmt ein TRUE werden.

von Peter D. (peda)


Lesenswert?

Daniel Bremenkamp schrieb:
> Und nun komme ich zu dem Teil, zu dem ich die meisten Kommentare
> erwarte: ich
> benutze den internen Oszillator mit 1MHz Taktrate.

Die Frequenz ist egal, hauptsache Du benutzt einen Quarz und das tust Du 
ja laut Schaltplan (1MHz).
Dann kannst Du die Uhr sehr genau einstellen.
Ich lasse die Uhr <4Wochen laufen und ermittele aus der Abweichung die 
genaue Quarzfrequenz. Dann trage ich die in die Source ein und 
compiliere neu. Danach läuft sie stabil (<1min/Jahr).
Der interne RC-Oszillator taugt dagegen bestenfalls als Eieruhr.

Daniel Bremenkamp schrieb:
> dass die Abweichung der Uhr erst dann zu groß wird wenn
> auch
> der Akku leer ist.

Das ist ja merkwürdig. Ein Quarz schwingt entweder fast 
spannungsunabhängig oder garnicht.

Daniel Bremenkamp schrieb:
> Um Strom zu sparen wird der Controller in der Idlezeit in einen
> Powerdown-Modus
> geschaltet

Nützt bloß nichts, wenn schon der Spannungsregler (5mA) deutlich mehr 
verbraucht, als der MC (1mA).
Nimm lieber 3 Mignon (4,5V) und verzichte ganz auf den Spannungsregler.
Und mit nem Uhrenquarz (32kHz) kannst Du wirklich Strom sparen (~1µA).


Peter

von MaWin (Gast)


Lesenswert?

> Ich arbeite aber an einer Lösung um die Spannung nur
> anzulegen wenn sie auch gemessen werden soll

Brauchst du nicht.
Du darfst den Spannungsteiler VIEL hochohmiger machen
(2M2 statt 2k2) wenn du von TP2 nach Masse einen
mindestens 10nF Kondensator legst, Folienkondensator.

>  bei etwa 7,3V fängt die Status-LED an zu blinken

Der Mindesteingangsspannung des 78L05.
Nimm lieber einen LP2950-5 als Spannungsregler.
erstens regelt der auch noch, wenn der 9V Batterieblock
leer ist (6V), zum anderen braucht der Regler VIEL weniger
Strom als die 5mA Eigenbedarf des 78L05, sondern nur noch
Mikroampere. Kondensatoren ans Datenblatt anpassen.

> ich benutze den internen Oszillator mit 1MHz Taktrate.

Du erwartest Kommentare, du bekommst Kommentare:
Der ATmega hat gar nicht so viel zu rechnen, daß er so
schnell sein müsste. Du kannst ihn problemlos auch mit
32.768khZ laufen lassen, Diese Quartze sind genauer und
der ATmega braucht bei so nedriger Frequenz DEUTLICH
weniger Strom.

Bleiben nur noch die bei dir von im Schnitt mit 1mA
durchflossenen LEDs.

Dazu nimmst du ein LCD Glas z.B. aus einem
Tamagotchi-Spielzeug, und schliesst das direkt an den
uC an. Sozusagen nächste Lernstufe, LED durch LCD
ersetzen, du ahst genügend Anschlüsse verfügbar.
Dann braucht die Schaltung fast gar keinen Strom mehr
und läuft jahrelang an der Batterie (bzw.
kann aus einer CR2320 Lithiumzelle versorgt werden).

von Daniel B. (daniel80)


Lesenswert?

Hallo,

erstmal Danke für eure Kommentare. Dann fange ich mal an zu Antworten:

@Uwe S.
Ja, TRUE als das Ergebnis einer boolschen Operation zu belegen verstehe 
ich. Ich habe mich für FALSE = 0 entschieden in der Annahme, dass der 
Compiler für die Bedingungen dann nur die entsprechende Variable laden 
muss und dann das Zero Flag prüft. Außerdem nahm ich an, dass der 
Compiler den Wert FALSE auch als = 0 setzt. Aber ich gebe dir natürlich 
vollkommen Recht, die eindeutige Definition sollte so sein wie du es 
beschrieben hast.
Die volatile Deklaration der in der isr benutzten Variablen sehe ich 
auch ein, mein Programm läuft bei mir aber trotzdem sauber. Könnte es 
nicht auch helfen die Variablen mit dem Schlüsselwort register zu 
deklarieren? Aber nicht jeder Compiler folgt dieser Anweisung...
Was ich nicht ganz verstehe ist der Vorteil die Funktionen als static 
anstelle inline zu deklarieren. Bei inline wird der Code doch vom 
Compiler an die entsprechende Stelle kopiert, oder?

@Jonas Quinn
Ich bin durchaus offen für Kritik, aber pauschal zu schreiben "sowas 
kompliziertes braucht man nicht" finde ich nicht ganz ok. Wenn ich es 
einfach haben will schaue ich auf meine Armbanduhr. Aber verstehe mich 
bitte nicht falsch: ich möchte dich hier nicht angreifen und ich möchte 
auch keine Diskussion über die Antworten die ich mir wünsche starten.

@Peter Dannegger
Im Schaltplan habe ich den Quarz als optional markiert (siehe 
Kommentarfeld). Und ich gebe dir auch vollkommen Recht, im Moment 
benutze ich die Uhr auch eher als Gimmick denn als "echte" Uhr. Ums 
wirklich genau zu haben würde ich natürlich auch einen Oszillator und 
evtl. einen Trimkondensator verwenden, damit die Frequenz wirklich 
korrekt ist. Das der Oszillator nicht spannungsabhängig ist weiß ich. 
Ich meinte mit meinem Kommentar, dass die Ungenauigkeit der Uhr erst 
wirklich merkbar wird wenn der Akku alle ist, und dann muss ich sie 
sowieso neu stellen. :-)
Ich habe auch schon überlegt einen anderen Controller und drei 
Mignonzellen zu nehmen um mir den Spannungsregler zu sparen. Ich benutze 
den 1MHz Quarz, damit die Anzeige nicht flackert. Aber da lässt sich mit 
den richtigen Parametern sicher was machen.

@MaWin
Ich habe die Werte für den Spannungsteiler so gewählt um mir keine 
Antenne zu bauen (so sagte mir ein Kollege). Aber die Lösung mit dem 
Kondensator ist natürlich so einfach wie wirksam. Danke für die Info!
Für die LEDs habe ich mich bewusst entschieden, weil ich die LEDs schon 
als Designelement verstehe. Wie würdest du denn die Zeit auf so einem 
LCD anzeigen (ich meine hier nicht die Ansteuerung sondern das Design 
der Anzeige)?

Und zum Schluss an alle: danke für eure Beiträge, hätte nicht gedacht 
dass in so kurzer Zeit schon so viele Beiträge kommen. Ich habe hier ja 
keine Frage im Sinne von "ich brauche schnelle Hilfe" gestellt. Super!

Schönen Abend beisammen,
Daniel

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.