Forum: Mikrocontroller und Digitale Elektronik Timerüberläufe zählen


von Matze (Gast)


Lesenswert?

Hallo liebe Leute,

ich möchte die verstrichene Zeit messen, die ein Kondensator zum 
Aufladen braucht. Dazu will ich mir mit einem Spannungsteiler zwei 
Referenzspannungen erzeugen und diese mit der am Kondensator anliegen-
den Spannung vergleichen.
Ich nutze ein C-Control Pro 128 mit amtel mega 128 :-)

Es soll also ein Timer aktiviert werden, wenn die untere 
Referenzspannung erreicht wird und wieder
gestoppt, wenn die obere Referenzspannung erreicht wird.

Ich habe mit gedacht: Der Timer zählt in 4,36 µs - Schritten, bis er 
überläuft und von vorn anfängt.
Die Anzahl der Überläufe  diskrete Schritte des Timers  Schrittweite + 
Aktueller Timerstand
* Schrittweite müsste dann doch theoretisch die Aufladezeit ergeben?!

Um das üben habe ich mal versucht, einen Timer 500 ms lang laufen zu 
lassen und dann die Anzahl
der Überläufe zu zählen:

Dim counter As Word
Dim Zahl, Zaehler As Word

Sub Ausgabe(Zahl As Word)

     LCD_Init()
     LCD_CursorPos(1)
     LCD_WriteWord(Zahl,5)

End Sub

Sub Counter()

    Zahl = Zahl + 1
    Msg_WriteWord(Zahl)
    Msg_WriteChar(0x0D)
    Irq_GetCount(INT_TIM3OVF)


End Sub




Sub main()

               Timer_T3Start(PS_64)
               Irq_SetVect(INT_TIM3OVF,Counter)
               AbsDelay(1000)

               Timer_T3Stop()
               Zaehler=Timer_T3GetCNT()
               'Msg_WriteWord(Zahl)
               Ausgabe(Zaehler)

End Sub


Es funktioniert leider gar nicht :-(

Ihr würdet mir sehr weiterhelfen, wenn ich einen Tip bekommen könnte.


Schöne Grüße


Mathias

von Phipps (Gast)


Lesenswert?

hallo,

was bedeutet den es funktioniert gar nicht? Evtl liegt es daran das die 
Zahl zu klein ist bei über 100.000 Überlaufen?

von Peter D. (peda)


Lesenswert?

Matze schrieb:
> ich möchte die verstrichene Zeit messen, die ein Kondensator zum
> Aufladen braucht.

Wozu?

Leg erstmal fest, wie bei jeder Meßaufgabe:
- Min-Wert
- Max-Wert
- Auflösung
- Genauigkeit
- Meßrate
Vorher sind alle Deine Fragen sinnlos.

Schau Dir mal den Analog-Komparator und den Input-Capture an, die sind 
genau dafür gedacht.

von Matze (Gast)


Lesenswert?

Es sollen Kapazitäten im Bereich von 20 pF < C < 100 pF gemessen werden.

Dazu soll die Beziehung tau = C · R verwendet werden.
Über die Kapazität eines Sensors bzw. einer Kapazitätsänderung am Sensor 
soll  dann mit Hilfe der "effective medium approximation" der 
Massenanteil von Stäuben in Aerosolen bestimmt werden. Darüber kann der 
Trenngrad eines Abweiseradsichters ermittelt werden. Aber das tut für 
meine eigentliche Messaufgabe nichts zur Sache, denke ich.

Der Aufladevorgang des Sensors soll in der Größenordnung von 20 ms - 100 
ms lang dauern. Der Analogkomparator soll die Spannung am Kondensator 
mit zwei Referenzspannungen (1,3 V und 2,6 V) vergleichen und die Zeit 
Messen, die zum Durchgang von Referenzspannung 1&2 verstreicht.

Auf der C-Control 128 gibts einen 16bit Timer, der nach 65.536 Steps 
überläuft. Ich möchte jetzt, dass der Timer mit 4,34 µs als Zeitbasis 
zählt. bei 65.536 Steps sind das 284 ms Zählzeit, bis überlauf.

Ich wollte jetzt aber die Genauigkeit steigern und eine kleinere 
Zeitbasis wählen. Dann läuft der Timer aber über. Um das zu umgehen 
möchte ich gerne die Überläufe Zählen und daraus dann die verstrichene 
Zeit messen.

Mein Problem ist jetzt, dass ich es nicht schaffe, die Überläufe eines 
Timers zu zählen. Noch ohne Spannungen und alles, sondern einfach zum 
Üben...

von J. T. (chaoskind)


Lesenswert?

Richte den Timer ein das du im FastPWMMode bist, dann bekommste  bei 
jedem Überlauf einen Interrupt. Interrupts natürlich mitaktivieren. In 
der ISR inkrementierst du dann nen Register das dir deine Überläufe 
zählt. Siehe Datenblatt unter Timer, da mal die Registerdefinitionen 
anschauen

MfG Chaos

von Karl H. (kbuchegg)


Lesenswert?

In der Hilfe zu "AbsDelay" lese ich
1
Die Funktion Absdelay() wartet eine bestimmte Anzahl von Millisekunden.
2
 
3
Die Funktion arbeitet zwar sehr genau, aber unterbricht nicht nur die
4
Abarbeitung des aktuellen Threads, sondern läßt den Bytecode Interpreter
5
insgesamt warten. Interrupts werden zwar registriert, aber die
6
Interruptroutinen in dieser Zeit nicht abgearbeitet, da auch dafür der
7
Bytecode Interpreter nötig ist.

Überleg mal, was wohl der letzte Satz in deinem Fall für Konsequenzen 
haben könnte.

(Ich sag könnte, weil ich von der C-Control, bzw. ihrem Framework nicht 
die geringste Ahnung habe. Aber wenn schon die offizielle Doku sagt, 
dass Interrupt Routinen während eines AbsDelay nicht abgearbeitet 
werden, dann wird das ja nicht von ungefähr kommen)

von Peter D. (peda)


Lesenswert?

Matze schrieb:
> Es sollen Kapazitäten im Bereich von 20 pF < C < 100 pF gemessen werden.

Das ist ein Dynamik-Bereich von 1:5, da kommst Du bequem mit einem 
16bit-Timer aus.

Matze schrieb:
> Der Aufladevorgang des Sensors soll in der Größenordnung von 20 ms - 100
> ms lang dauern.

Ergibt 1 Giga-Ohm Ladewiderstand, vergiß es.
Ein Fingerabdruck auf der Platine ist ja schon niederohmiger.

von Matze (Gast)


Lesenswert?

Vielen Dank erstmal für die hilfreichen Antworten.

Den ganzen Aufbau habe ich von hier:
http://www.spurtikus.de/basteln/capmeter/index.html

Ich will ihn nicht 1:1 nachbauen, sondern die Theorie dazu auch 
verstehen.

Da ist von 75 ms Ladezeit die Rede...

von Matze (Gast)


Lesenswert?

Das Programm unten müsste jetzt (so wie ich es aktuell verstehe) 
folgendes tun:

Timer geht an, immer wenn er bis 500 gezählt hat, geht er in den 
interrupt.
Da wird dann ein counter hochgezählt.
In der Schleife wird zum Überprüfen, ob der Timer läuft, der Wert des 
timers aufm Display ausgegeben. Wenn der Timer 10 mal geinterrupted hat, 
ist das Programm beendet.

Wenn das Programm gestartet wird, wird nie in die Interrupt gesprungen. 
Das Prog. hängt in der Schleife und gibt fortlaufend den immer von vorne 
hochzählenden timer aus.

Woran kann das liegen?



Dim counter As Word
Dim Zahl, Zaehler As Word


Sub Ausgabe(Zahl As Word)
    'LCD Init
     LCD_Init()
     LCD_CursorPos(1)
     LCD_WriteWord(Zahl,5)
End Sub



Sub Counter()

    Dim irqcnt As Byte
    Zahl = Zahl + 1
    Msg_WriteWord(Zahl)

    Msg_WriteChar(0x0D)
    irqcnt=Irq_GetCount(INT_TIM3CMPA)


End Sub




Sub main()

 Zahl = 0
 Timer_T3Time(500,PS_1024)
 Irq_SetVect(INT_TIM3CMPA,counter)

      Do While Zahl < 10
            Zaehler=Timer_T3GetCNT()
            Ausgabe(Zaehler)
     End While
  Timer_T3Stop()
End Sub

von Sascha W. (sascha-w)


Lesenswert?

Matze schrieb:
> Das Programm unten müsste jetzt (so wie ich es aktuell verstehe)
> folgendes tun:
>
> Timer geht an, immer wenn er bis 500 gezählt hat, geht er in den
> interrupt.
> Da wird dann ein counter hochgezählt.
> In der Schleife wird zum Überprüfen, ob der Timer läuft, der Wert des
> timers aufm Display ausgegeben. Wenn der Timer 10 mal geinterrupted hat,
> ist das Programm beendet.
ok & siehe unten

> Wenn das Programm gestartet wird, wird nie in die Interrupt gesprungen.
> Das Prog. hängt in der Schleife und gibt fortlaufend den immer von vorne
> hochzählenden timer aus.
Ausgabe "timer" == Ausgabe "Zahl" ??
wenn die hochzählt, dann funktioniert auch der Interrupt, wie sollt 
sonst Zahl größer werden!

> Woran kann das liegen?
was glaubst du was nach "End Sub" von <Main> passiert, ich vermute da 
kommt ein reset und dein Programm geht wieder von vorn los.

> Sub Counter()
>
>     Dim irqcnt As Byte
>     Zahl = Zahl + 1
<-- die Ausgabe sollte aber nicht länger als die Dauer zwischen zwei 
Interrupts dauern, sonst wirds Mist
>     Msg_WriteWord(Zahl)
>     Msg_WriteChar(0x0D)
-->
>     irqcnt=Irq_GetCount(INT_TIM3CMPA)
zu was soll das gut sein??
>
> End Sub


Sascha

von Matze (Gast)


Lesenswert?

Nein, Zähler =| Zahl.

Zahl soll die Anzahl der Interrupts anzeigen und Zähler den Wert des 
Timers.

Laut Bibliothekenhandbuch muss Irq_GetCount am Ende der 
Interruptfunktion stehen:

Syntax

byte Irq_GetCount(byte irqnr);

Sub Irq_GetCount(irqnr As Byte) As Byte


Beschreibung

Signalisiert, daß der Interrupt abgearbeitet wurde (interrupt 
acknowledge). Wird die Funktion nicht am Ende einer Interruptroutine 
aufgerufen, wird ununterbrochen in den Interrupt gesprungen.

Parameter

irqnr  spezifiziert den Typ des Interrupts (siehe Tabelle)

Rückgabewert

Gibt an, wie oft der Interrupt von der Hardware bis zum Aufruf von 
Irq_GetCount() ausgelöst wurde. Ein Wert größer 1 kann dann auftreten, 
wenn die Hardware schneller Interrupts generiert, als der Interpreter 
die Interruptroutine abarbeiten kann.

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.