Forum: Compiler & IDEs Analog Uhr, GLCD, ?


von Holger G. (holli1195)


Lesenswert?

Schönen guten Abend zusammen!

Ich möchte in meinem Projekt gern eine Analoguhr darstellen. Für mein 
Projekt verwende ich die letzte Version von Holger Klabunde für KS0108 
(Pollin Display).In meinem Programm habe ich die Variablen h 
0-24(Stunden) und
m 0-60(Minuten) gespeist von einer DCF77 Routine. Nun sitze ich schon 4 
Abende vor meinem Rechner und grübel über eine Lösung nach. Hat sowas 
schon mal jemand von Euch versucht? Ich komme einfach auf keinen 
Lösungsweg.

P.S. Einen Kreis kann ich schon darstellen... ;-)

Gruß Holger

von STK500-Besitzer (Gast)


Lesenswert?

Schon mal was von "Bresenham" gehört?

von STK500-Besitzer (Gast)


Lesenswert?

Man sollte Threads auch zuende lesen...

Aber mit Hilfe des Bresenham-Algorithmus solltest du zu einem Ergebnis 
kommen. Aber wie, weiß ich jetzt auch nicht.

von Helmi (Gast)


Lesenswert?

Ich wuerde das Zifferblatt als Bitmap am PC erstellen und diese Daten 
auf dem Display ausgeben. Denn Zeiger kannst du dann mit dem Bresenham 
algorythmus darstellen. Wenn du die Bitmap am PC erstellst hast du viel 
mehr moeglichkeiten ein schoenes Zifferblatt hinzubekommen als wenn du 
es mit dem Bresenham Kreisalgo. im Controller zurecht zimmern wuerdest.

Gruss Helmi

von Karl H. (kbuchegg)


Lesenswert?

STK500-Besitzer wrote:

> kommen. Aber wie, weiß ich jetzt auch nicht.

Das weitere ist im Grunde relativ einfach:
Die Zeit (egal ob Minuten oder Stunden) ist ja im Grunde
nichts anderes als ein Winkel am Display. Man zeichnet
dann eine Linie (mit dem Bresenham) vom Mittelpunkt des
Kreises zum endsprechenden Endpunkt am Kreis.
Woher wissen wir die Koordinaten des Endpunktes?
Wie gesagt: Die Zeit ist nichts anderes als ein Winkel.
-> Hier kommt Trigonometrie zum Einsatz.

  x_end = x_mitte + radius * cos( Winkel );
  y_end = y_mitte + radius * sin( Winkel );

und dann wird eine Linie von x_mitte/y_mitte nach x_end/y_end
gezeichnet.

Bleibt nur noch die Bestimmung des Winkels:
Na, wenn 60 Minuten (am Beispiel des Minutenzeigers) einem Vollkreis,
also 360 Grad, bzw. 2*PI entsprechen, welchen Winkel legt der Zeiger
dann in 1 Minute zurück?

        60 ....  2*PI
         1 ....   x

            2 * PI
       x = ----------
              60

(oder gerechnet in Grad, da man dann schönere Zahlen hat: x = 360 / 60 = 
6)

d.h. wenn der Minutenzeiger auf 1 Minute steht, dann hat er einen Winkel
von 6 Grad. Steht er auf 2 Minuten, hat er 12 Grad, bei 3 Minuten auf
18 Grad, etc.

Was es jetzt noch zu berücksichtigen gilt:
Die Kreisfunktionen arbeiten entgegen dem Uhrzeiger. Der Minutenzeiger
dreht sich aber im Uhrzeiger. Da wird also wohl irgendwo eine
Vorzeichenumkehr notwendig sein.
Bei der üblichen Sichtweise der Kreisfunktionen liegt 0 Grad auf
der X-Achse waagrecht. Bei einer Uhr ist aber der 0 Punkt oben
(also dort wo bei den Kreisfunktionen 90 Grad liegt). Da wird
also auch noch eine Anpassung notwendig.
Die trigonometirschen Funktionen sin und cos wollen ihren Winkel
in Radianten und nicht in Grad.

Alles in allem ist das nicht weiter kompliziert. Sobald du eine
Linie von einem beliebigen Pixel zu einem beliebigen Pixel
ziehen kannst (dafür brauchst du den Bresenham) ist eine Uhr
weiter kein grosses Problem mehr sobald du die Stunden und
Minuten sauber vorliegen hast.

von Holger G. (holli1195)


Lesenswert?

Wie immer!!!!

Sekunden nach einer Anfrage - kompetente Antwort. Danke!
Ich glaube mit Bresenham brauch ich mich nicht weiter zu beschäftigen, 
die Lib kann alle möglichen Linien (auch von x1y1 nach x2y2) zeichnen. 
Werde ich gleich mal ausprobieren. x1y1 ist ja dann immer der 
Mittelpunkt. x2y2 zu berechnen sollte mir jetzt auch nicht mehr schwer 
fallen... jetzt bleibt nur noch ein Punkt: ich habe die Minuten und 
zugehörig x2y2. Wie lege ich das jetzt elegant ab? Ich würde es mal mit 
einer switch(m) versuchen. Ist aber bestimmt kein guter 
Programmierstil....


Gruß Holger

von Karl H. (kbuchegg)


Lesenswert?

Holger Gerwenat wrote:

> fallen... jetzt bleibt nur noch ein Punkt: ich habe die Minuten und
> zugehörig x2y2. Wie lege ich das jetzt elegant ab? Ich würde es mal mit
> einer switch(m) versuchen.

Wenn schon, dann würde man das mit einer Tabelle machen, aber ...

> Ist aber bestimmt kein guter
> Programmierstil....

... wenn die Uhr das einzige ist, was in dem µC abläuft, dann
hast du von einem Hinzeichnen zum nächsten Hinzeichnen
genau 1 Sekunde Zeit. Weist du wieviele sin() / cos() dein
µC in dieser Zeit berechnen kann? Zwar nicht Millionen
wie ein PC aber ein paar Hundert kriegt er auch hin.

-> Wenn also ausser der Uhr nichts anderes laufen soll, dann
lohnt sich der ganze Aufwand nicht. Berechne die Position
einfach neu, wenn du sie brauchst.

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Es geht auch einfacher. Jede Minute den Endpunkt mit einer 
Rotationsmatrix multiplizieren um den neuen Endpunkt zu bekommen. Wegen 
Rundungsfehlern muß man allerdings jede Stunde den Zeiger neu 
Initialisieren.

Ich habe eine Exceldatei zur Demonstration angehängt. Die Zahlen 1018 
und 107 sind Konstanten und müßen im Controller nicht Berechnet werden. 
So sind jede Minute nur 4 Multiplikationen und ein paar Additionen 
notig.

Mfg Michael

von Simon K. (simon) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ich hab das mal Testweise mit einer Lookuptable (aus einem Excel 
Dokument) gemacht. Für ein T6963c

Das Excel Sheet, was beiliegt erzeugt zwei Tabellen (Für den kurzen und 
für den Langen Zeiger jeweils eine). Du kannst im Excelsheet einfach die 
Zellen markieren, kopieren und im Code-Editor deiner Wahl richtig 
eingerückt einfügen.

von Holger G. (holli1195)


Lesenswert?

Vielen Dank für Eure Antworten!
und daß Ihr mir immer so geduldig helft

Ich werde am Wochenende mal beide Varianten (direkte Berechnung und 
Tabelle) probieren. Mal sehen, wie weit meine beschränkten 
Progammierkenntnisse reichen. Ich werde berichten...

Bis dahin
Gruß Holger

von STK500-Besitzer (Gast)


Lesenswert?

Sehe ich es richtig, dass man bei (spartanischen) Zeigern eigentlich nur 
pro Zeiger eine Tabelle mit 60 (Koordinaten-)Werten haben müsste?
Das sollte ja amchbar sein...

von Karl H. (kbuchegg)


Lesenswert?

STK500-Besitzer wrote:
> Sehe ich es richtig, dass man bei (spartanischen) Zeigern eigentlich nur
> pro Zeiger eine Tabelle mit 60 (Koordinaten-)Werten haben müsste?
> Das sollte ja amchbar sein...

Das siehst du richtig.

von Peter D. (peda)


Lesenswert?

STK500-Besitzer wrote:
> Sehe ich es richtig, dass man bei (spartanischen) Zeigern eigentlich nur
> pro Zeiger eine Tabelle mit 60 (Koordinaten-)Werten haben müsste?
> Das sollte ja amchbar sein...


Sofern die Pixel quadratisch sind, reichen 3 Stundenzeiger und je 15 
Minuten- und Sekundenzeiger.
90° Drehung (X,Y bzw. Vorzeichen vertauschen) ist ja kein Rechenaufwand.


Peter

von der mechatroniker (Gast)


Lesenswert?

Es gibt aber bei einer Analoguhr mehr als 12 Stellungen des 
Stundenzeigers. Der ist nämlich, wie der Name schon sagt, analog.

von STK500-Besitzer (Gast)


Lesenswert?

>Sofern die Pixel quadratisch sind, reichen 3 Stundenzeiger und je 15
>Minuten- und Sekundenzeiger.
>90° Drehung (X,Y bzw. Vorzeichen vertauschen) ist ja kein Rechenaufwand.

Da war wohl noch Optimierungspotential vorhanden...
Das wäre dann eine Variante des Bresenham bzw. die Anwendung des 
gleichen...

von Falk B. (falk)


Lesenswert?

@ der mechatroniker (Gast)

>Es gibt aber bei einer Analoguhr mehr als 12 Stellungen des
>Stundenzeigers. Der ist nämlich, wie der Name schon sagt, analog.

Jaja, die Haarspalter mal wieder. Schon mal was von Quantisierung 
gehört?

MfG
Falk

von Philipp B. (philipp_burch)


Lesenswert?

Falk Brunner wrote:
> @ der mechatroniker (Gast)
>
>>Es gibt aber bei einer Analoguhr mehr als 12 Stellungen des
>>Stundenzeigers. Der ist nämlich, wie der Name schon sagt, analog.
>
> Jaja, die Haarspalter mal wieder. Schon mal was von Quantisierung
> gehört?

Also das würde ich nun keinesfalls als Haarspalterei bezeichnen. 
Einfaches Beispiel: 7:59 Wenn der Stundenzeiger immer noch präzise auf 
der Sieben hockt, dann ist es nicht so leicht zu erkennen, ob es jetzt 
fast 8:00 oder eher 7:00 ist, besonders bei einem eher kleinen Radius 
des Zeigers und etwas Abstand zum Display. Also wenigstens 48 Schritte 
würde ich dem Stundenzeiger schon spendieren, dann kannst du daran auch 
noch Viertelstunden noch mehr oder weniger ablesen.

von Falk B. (falk)


Lesenswert?

@  Philipp Burch (philipp_burch)

>Also das würde ich nun keinesfalls als Haarspalterei bezeichnen.
>Einfaches Beispiel: 7:59 Wenn der Stundenzeiger immer noch präzise auf
>der Sieben hockt, dann ist es nicht so leicht zu erkennen, ob es jetzt
>fast 8:00 oder eher 7:00 ist, besonders bei einem eher kleinen Radius

Ach so! Ja, stimmt natürlich.

MfG
Falk

von Peter D. (peda)


Lesenswert?

der mechatroniker wrote:
> Es gibt aber bei einer Analoguhr mehr als 12 Stellungen des
> Stundenzeigers. Der ist nämlich, wie der Name schon sagt, analog.

Dann eben 12 Stundenzeiger für 1/4h Anzeige.

Ob nun 33 oder 42 Zeigerbilder im Flash, dürfte ja kein großer 
Unterschied sein.

Die Bilder hätten außerdem den Vorteil, daß man 3 beliebig geformte 
Zeiger definieren kann (ohne, mit Bauch, dick, dünn, spitz, gerade usw.)

Die verschiedenen Formen machen es einfacher, übereinander liegende 
Zeiger zu unterscheiden.


Peter

von Stefan K. (_sk_)


Angehängte Dateien:

Lesenswert?

Hallo Holger,

habe Dir mal meine Uhrendarstellung angehängt. Das Ganze ist nicht 
besonders dokumentiert, ich hoffe, es reicht Dir.

Die Darstellung beruht auf dem Bresenham-Algorythmus, ich habe den in 
der Wikipedia gefundenen etwas geändert.

Das Array uhr[] ist für die 12 kleinen Aussenstriche zuständig.

Die Zeiger haben jeweils nur 15 Einträge, die restlichen 3 Quadranten 
werden aus diesen 15 Werten berechnet.

Der Minutenzeiger ist nur 1 Pixel breit,
Der Stundenzeiger ist 2 Pixel breit.

Ich verwende ein 128 * 64 Graphik-LCD, bei größeren Displays musst Du 
ggf. manche Werte von uint8_t auf uint16_t ändern.

Die einzige Routine, die aus der Graphikbibliothek (ich benutze meine 
eigene) verwendet wird, ist
  setpixel(x, y);
Das musst Du ggf. an die verwendete lib anpassen.

Viel Spaß und viele Grüße, Stefan

von Holger G. (holli1195)


Angehängte Dateien:

Lesenswert?

Ich bitte vielmals um Entschuldigung!

Ich hatte mir eine schlimme Erkältung zugezogen und hinterher war so 
viel dienstliche Arbeit da, daß ich überhaupt nicht zum programmieren 
gekommen bin und mein Projekt einfach stehen blieb.
@ Stefan:
Gestern Abend habe ich den Code mal ausprobiert. - Genial!
Genau das hatte ich gesucht und mich dann schon selber dran versucht.
Vielen Dank Stefan - funktioniert prima.

P.S. den Kreis hab ich zugefügt

Gruß Holger

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.