Forum: Mikrocontroller und Digitale Elektronik Genaue Sekunde mit 4,194304Mhz Quarz: kleine Probleme..


von Draco (Gast)


Lesenswert?

So nun hat es mich auch in diese doofe Situation verschlagen :/

Ich möchte eine Sekunde ziemlich genau messen damit ich Ah ausrechnen 
kann. Ich habe einen 4,194304 Mhz Quarz im Einsatz mit einem Teiler von 
256 komme ich genau auf 16384 Zyklen.

Jedoch weiß ich nun nicht welchen Timer bzw. Interrupt ich wo und vor 
allem wie ansprechen muß das ich diese genaue Sekunde erhalten. :/

In meinem Programm habe ich bereits einen Timer2 Overflow, für meinen 
Drehimpulsgeber laufen, welcher jedoch bei jedem Drehimpuls eine Pause 
von 50ms einlegen muß (läßt sich leider bei der Bitabfrage des doofen 
Impulsgebers nicht anders ändern :/) Kann ich denn dann einen zweitern 
Timer nebenbei laufen lassen?! Oder sollte ich mir da tunlichst was 
anderes einfallen lassen?!

Achja... µC ist ein Atmega32 und schreiben tue ich in MicroC - geht aber 
auch das normale AVR GCC...

Vielen Dank für eure Hilfe!

von Stefan B. (Gast)


Lesenswert?

In erster Näherung kannst du IMHO den Timer2 Overflow mitbenutzen (20 * 
exakt 50ms = exakt 1s). Genauer könnte man was dazu sagen, wenn man 
wüsste, aus welchen Messungen und wie du die Kapazität (Ah) berechenen 
willst.

von Ich (Gast)


Lesenswert?

Hallo was ist mit Timer 0?
Ich würde nicht alle 256 Takte in die ISR hüpfen. Da diese ja selbst 
wenn du nur einen 8Bit Zähler hoch zählen willst etliche Takte benötigt 
und du so eine hohe Auslastung hast. (Gut bei einem Zähler geht's noch 
gerade so ;)

von Falk B. (falk)


Lesenswert?

@  Draco (Gast)

>So nun hat es mich auch in diese doofe Situation verschlagen :/

Ach du Aaaaaaarmer.

>Ich möchte eine Sekunde ziemlich genau messen damit ich Ah ausrechnen
>kann. Ich habe einen 4,194304 Mhz Quarz im Einsatz mit einem Teiler von
>256 komme ich genau auf 16384 Zyklen.

Und wo ist das Problem?

Siehe AVR - Die genaue Sekunde / RTC

>In meinem Programm habe ich bereits einen Timer2 Overflow, für meinen
>Drehimpulsgeber laufen, welcher jedoch bei jedem Drehimpuls eine Pause
>von 50ms einlegen muß (läßt sich leider bei der Bitabfrage des doofen
>Impulsgebers nicht anders ändern :/)

Unsinn. Im Interrupt wird NIE gewartet, schon gar nicht 50ms!!!
Siehe Interrupt.
Kann man alles anders programmieren, man muss nur wissen wie. Siehe auch 
Multitasking.

> Kann ich denn dann einen zweitern
>Timer nebenbei laufen lassen?! Oder sollte ich mir da tunlichst was
>anderes einfallen lassen?!

Ja, vergiss die Murksprogrammierung und lerne wie man es richtig macht.

MFG
Falk

von avr (Gast)


Lesenswert?

Die 4,194304 MHz sind 2^22 Hz, daher kommt auch der Wert.

Bei den Zählern gibt es daher die Möglichkeiten mit Overflow:

8 Bit-Zähler (2^8) mit Vorteiler 1024 (2^10) und eigener
Zähler bis 16 (2^4), d.h. ein Zeitfenster von 62,5 ms.

16 Bit-Zähler (2^16) mit Vorteiler 64 (2^6) ergibt direkt
1 Sekunde.

Wenn du statt deinen 50 ms mit den 62,5 ms leben kannst
wäre das der beste Weg.

AVR

von Draco (Gast)


Lesenswert?

Na die 50ms kommen nur dann zustande wenn der Impulsgeber eine Drehung 
vollführt.:
1
void Timer2Overflow_ISR() org IVT_ADDR_TIMER2_OVF
2
{
3
     if (Button(&PINC, 2, 1, 1) && Button(&PINC, 4, 1, 0) && richtung == 0) {
4
                       richtung = 2;
5
                       delay_ms(50);
6
7
     } else if (Button(&PINC, 4, 1, 1) && Button(&PINC, 2, 1, 0) && richtung == 0) {
8
                       richtung = 1;
9
                       delay_ms(50);
10
11
     }
12
}
13
14
15
....
16
  SREG_I_bit = 1;
17
  TOIE2_bit  = 1;
18
  TCCR2      = 6;
19
....

Ich messe die aktuelle Spannung einer (Solarzelle + Batterie - 
Verbraucher) via ADC alle 10sec und möchte mir die Ergebnisse einfach 
aufaddieren. Mir reicht es ja wenn ich erst nach 2-3h das Ergebniss 
sehe, das funktioniert ja auch soweit ganz gut :D Jedoch komme ich mit 
dem Timer nicht so ganz auf die Sekunde, weil mir fehlt entweder immer 
was oder ich bin nach 2-3 Minuten schon 2sec im vorraus.

von Purzel H. (hacky)


Lesenswert?

Einen Delay im Timer Interrupt ? Aaaaaaaaaaaaaaaaaaahhhhhhhhhhhhhhhhh.

von Herbert K. (avr-herbi)


Lesenswert?

Hallo,
ich meine, zu einer halbwegs genauen Zeit wirst Du erst kommen, wenn Du 
andersherum von Deiner Anforderung den Quarz berechnest.
Also was ich meine:
Bei 8 Bit Timer:
z.B. per Software z.B. (50 x Interrupt und per Software zählen)
x Hardware Teiler des Timers x Vorteiler => Quarz
Da der 16 Bit Timer von Dir schon verwendet wird, schlage ich Dir den 
Timer 2 dafür vor, da kannst Du mit Überlauf Interrupt arbeiten. Den hat 
Timer0 nicht. (Hab mich damit leider vor einigen Tagen selbst 
auseinandersetzten müssen und mich viel Zeit gekostet).
Wenn Du von einem Quarz ausgehst wie bisher, wirst Du vermutlich immer 
auf Teilerfaktoren kommen, die nicht ganzzahlig sind und dann wirds 
vermutlich ungenau.
Viele Grüße Herbert

von Draco (Gast)


Lesenswert?

Ja und?! Momentan wurde der Timer auch ausschließlich für die 
Drehgeberabfrage genutzt. Es funktioniert wunderbar, das Programm war 
nicht zeitkritisch - also warum nicht?! Ist nicht schön, ich weiß. Aber 
das Ergebniss ist das Ziel - nicht der Weg.

Das ich es nun umschreiben muß ist mir klar. Aber solche Postings 
bringen einen echt nicht weiter. Ich hab mir hierher gewandt weil ich 
ein Problem habe und ein Meister noch nie vom Himmel gefallen ist - auch 
ihr habt mal angefangen und Fehler begangen. Jemanden deswegen "dumm" zu 
machen sehe ich als falschen Ansatz in einem Forum wie diesem.


Vielen Dank erstmal für die Hinweise, auch an Falk für die nützlichen 
Links. Werde mich da mal reinlesen.

von Draco (Gast)


Lesenswert?

Mensch.. so schnelle Antworten hier :D

Herbert K. schrieb:
> Hallo,
>
> ich meine, zu einer halbwegs genauen Zeit wirst Du erst kommen, wenn Du
> andersherum von Deiner Anforderung den Quarz berechnest.
> Also was ich meine:
> Bei 8 Bit Timer:
> z.B. per Software z.B. (50 x Interrupt und per Software zählen)
> x Hardware Teiler des Timers x Vorteiler => Quarz
> Da der 16 Bit Timer von Dir schon verwendet wird, schlage ich Dir den
> Timer 2 dafür vor, da kannst Du mit Überlauf Interrupt arbeiten. Den hat
> Timer0 nicht. (Hab mich damit leider vor einigen Tagen selbst
> auseinandersetzten müssen und mich viel Zeit gekostet).
> Wenn Du von einem Quarz ausgehst wie bisher, wirst Du vermutlich immer
> auf Teilerfaktoren kommen, die nicht ganzzahlig sind und dann wirds
> vermutlich ungenau.
> Viele Grüße Herbert

So wie ich mich gerade belesen habe im Datenblatt, ist der Timer2 einer 
der 8Bit Timer, also steht mir ja der 16Bit Timer (TCCR1) noch zur 
Verfügung. Dort passt mein Teiler ja wieder.

von spess53 (Gast)


Lesenswert?

Hi

>Timer 2 dafür vor, da kannst Du mit Überlauf Interrupt arbeiten. Den hat
>Timer0 nicht. (Hab mich damit leider vor einigen Tagen selbst
>auseinandersetzten müssen und mich viel Zeit gekostet).

Alle Timer des ATMega32 haben einen Overflow-Interrupt.

MfG Spess

von Herbert K. (avr-herbi)


Lesenswert?

Hallo,
bitte um Entschuldigung - war noch ein wenig früh. ATmega32 hatte ich 
übersehen. Ich war vom ATmega8 ausgegangen.

Aber ein Delay gehört eigentlich nicht in die ISR sondern das macht mann 
außerhalb der ISR - oder?

Nach dem ich anfangs ähnliche Probleme hatte, habe ich mein Prg. 
geändert, so das in der ISR nur Zustände abgefragt / festgehalten werden 
und evt. Counter +1.

Die Regelung / Steuerung mache ich dann außerhalb der ISR im normalen 
Programm, in dem die vorherigen Zustände einfach in einer Schleife 
abgefragt werden und da stört dann auch ein Delay nicht unbedingt. Seit 
dem läuft meine Uhr auch genauer.

Viele Grüße Herbert

von spess53 (Gast)


Lesenswert?

Hi

>bitte um Entschuldigung - war noch ein wenig früh. ATmega32 hatte ich
>übersehen. Ich war vom ATmega8 ausgegangen.

Auch alle Timer des ATMega8 haben einen Overflow-Interrupt.

MfG Spess

von Herbert K. (avr-herbi)


Lesenswert?

Hallo,
Spess hat mich wieder mal auf einen Fehler hingewiesen:
Ich meinte "Timer/Counter xx Compare Match" als ISR.
Danke Spess.
Viele Grüße Herbert

von Ich (Gast)


Lesenswert?

Aber wenn du in deinem einem Interrupt 50ms wartest. Verpasst du aber 
vielleicht den einen oder anderen Interrupt, da während eines Interrupt 
alle anderen gesperrt sind.

Wen ein anderer Interrupt z.B alle 10ms kommt verpasst du ca. 4 mal den 
anderen. So kommst du nie auf eine genaue Sekunde.

von Simon K. (simon) Benutzerseite


Lesenswert?

Es ist egal, ob der Weg das Ziel ist oder nicht, denn Warteschleifen in 
Interrupts sind No-Gos. Sowas macht man nicht. Und wie du siehst hast du 
deswegen auch Probleme.
Entprellung löst man anders als über Warteschleifen.

von Draco (Gast)


Lesenswert?

Gut gut, um nun mal ein wenig ruhe in den thread zu bringen hab ich die 
Tastenabfrage angepasst.:
1
 void Timer2Overflow_ISR() org IVT_ADDR_TIMER2_OVF
2
{
3
     if (Button(&PINC, 2, 0, 1) && Button(&PINC, 4, 0, 0) && richtung == 0 && zaehler >=29) {
4
                              richtung = 2;
5
                              zaehler = 0;
6
7
     } else if (Button(&PINC, 4, 0, 1) && Button(&PINC, 2, 0, 0) && richtung == 0 && zaehler >=29) {
8
                              richtung = 1;
9
                              zaehler = 0;
10
     }
11
     
12
     zaehler++;
13
}

Hab nun den 16Bit Timer mit 64iger Teilung genommen für meine sekunde, 
die Uhr läuft nun seit ca. 8h ohne eine sekunde abweichung, will sie 
dann morgen mal einen ganzen Tag neben einer Stopuhr laufen lassen.

Danke für eure Hilfe!

von Herbert K. (avr-herbi)


Lesenswert?

Hallo,
schön das wir Dir helfen konnten.

Ich freue mich auch, das Du für andere die Änderung / Lösung 
hinterlassen hast.

Viel Erfolg bei den weiteren Arbeiten am Projekt.
Viele Grüße Herbert

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.