Forum: Mikrocontroller und Digitale Elektronik Comparator mit Timer/Counter1


von R. Q. (timebeast)


Angehängte Dateien:

Lesenswert?

Moin,
also eigendlich bin ich nun wirklich kein Neuling im AVR Proggen, aber 
das
überfordert mich irgendwie.
Es geht um einen ATmega8, programmiert wird in ASM unter AVR-Studio 
4.13.

Also ich möchte den Comparator dazu bringen das er mir den 
Timer/Counter1 hochzählt beim auslösen.

Was bisher geht:
Also ich hab den Analog Comperator soweit das er mit einen Interrupt 
ausführt. Sprich er bekommt mit wenn negativ:AIN1 (PD7) und 
positiv:AIN0(PD6) sich abwechseln.

Desweiteren habe ich den Timer/Counter1 soweit das er OC1A (PB1)bzw. 
OC1B (PB2) toggelt wenn OCR1A bzw. OCR1B erreicht wurde. Allerdings 
"nur" wenn ich ihm sage das er keinen Prescaler verwenden soll (mit 
jedem anderen Prescaler würde es wahrscheinlich auch funktionieren).

Was nicht geht:
Ich aktiviere nun im ACSR Register des Comperators das Bit ACIC und 
schalte als Prescaler einen Externen Clock ein.

Wenn ich nun an AIN1 und AIN0 wieder meinen Impuls setzte (der 
Nachweislich funktioniert da eine Interrupt Routine ausgeführt wird -> 
anderes Programm) sollte er doch eigendlich den Timer/Counter1 
hochzählen, macht er aber nicht. Weder mit fallender noch mit steigender 
Flanke.

Ich hänge meinen bisherigen Code mal an, allerdings sind die Kommentare 
natürlich mit vorsicht zu genießen, da ich schon sehrviel mit 
rumgespielt habe. Also z.B. hab ich im "Datenblatt" gelesen, das ich 
ICR1 nicht als TOP definieren darf, da ansonsten die externen Trigger 
ausgeschaltet werden, usw.

Ich hoffe einer kann mir helfen, oder hat das vielleicht schonmal 
gemacht und kann mir einen Beispiel Code dazu senden.

P.S.: liegt es vielleicht am Input Capture Flag das ich clearen muß. Ich 
denke allerdings das muß man nur, wenn man zum Programmlauf die Trigger 
Source umstellen will, wenn ich das richtig verstehe....Ralf ratlos :-(

Gruß
Ralf

von Rahul D. (rahul)


Lesenswert?

Ich habe keinen Blick auf dein Programm geworfen, weil ich mit Assembler 
gerade nichts anfangen kann.
Hast du dir das Bild auf Seite 75 (Figure 32) angeguckt?
Der Analog-Komparator kann als alternative ICP-Quelle genutzt werden, 
aber nicht zum zählen.

von R. Q. (timebeast)


Lesenswert?

Wau, danke Rahul,
Du hast natürlich völlig recht, daher komm ich mit der Erklärung auch 
durcheinander.
Jetzt stellt sich mir die Frage, was erwartet er denn am input Capture 
Pin (ICP1) bzw. meinem Analog Comparator Ausgang (AC0)??

Ich meine, ich sehe daraus das der Pin irgendwie in das ICRn 
(Register?!? hä?) geschrieben wird. Aber ich geb doch nur ein Bit rein?
Und dann macht er daraus mein "TOP Value" wenn ich das richig 
interpretiere. Aus einem Bit generiert er das Top Value von 16Bit?? Wie 
geht das denn?

Ich meine, mir ist schon klar das meine Frage schon so ist, übersetz mir 
bitte mal das Datenblatt... puh... eigendlich kann ich Englisch... aber 
ich versteht´s nicht...

Hilfe?!?

äääh, Bitte?!?

:-)

von R. Q. (timebeast)


Lesenswert?

Ah, oky, also wenn AC0 ausgelöst wird schreibt er den Wert den er bis 
dahin hochgezählt hat (TCNT1) in das Input Capture Register (ICR1).

Hm, oky, nerv, er zählt nicht,...nicht ansatzweise, naja, zumindest ist 
jetz klar warum es nicht funktioniert ;-)

Danke nochmal,
muß ich halt anders hochzählen, danke zumindest nochmal

Gruß Ralf

von AVRFan (Gast)


Lesenswert?

>Ich meine, ich sehe daraus das der Pin irgendwie in das ICRn
>(Register?!? hä?) geschrieben wird.

Nein, nicht der Pin, sondern der aktuelle Zählerstand, also TCNT1, wird 
bei einem "Ereignis" am ICP-Pin augenblicklich ins ICR1-Register 
kopiert.  Welches Ereignis es sein soll, kann man festlegen auf 
"fallende Flanke", "steigende Flanke" oder "fallende und steigende 
Flanke".  Das "augenblicklich" ist wörtlich zu nehmen: der Kopiervorgang 
findet im selben Taktzyklus (!) statt - das ist das Besondere am Input 
Capture.  Mit einem Externen Interrupt kann man das nicht schaffen; dort 
könnte man TCNT1 erst einlesen, wenn das Programm im INterrupthanler 
gelandet ist, und das dauert ja so seine Zeit (mindestens ein paar 
Taktzyklen).

Den Input Capture-Vorgang kannst Du auch vom Analog Comparator-Ausgang 
triggern lassen, über das Bit ACIC im ACSR.

Klarer geworden?

von AVRFan (Gast)


Lesenswert?

>Also ich möchte den Comparator dazu bringen das er mir den
>Timer/Counter1 hochzählt beim auslösen.

Etwas verrückte Lösung: Toggle doch irgendeinen als Ausgang 
konfigurierten Pin im Analog-Comparator-Interrupt.  Diesen Pin 
verbindest Du mit Pin T1 (= PD5 beim ATmega8).  Dann nur noch über 
TCCR1B den Modus "external clock, triggered by [rising/falling] edge" 
für T/C1 wählen - fertig ist die Laube :-)

von Hannes L. (hannes)


Lesenswert?

Wenn Du die Impulse am Analog-Komparator zählen willst, dann brauchst Du 
dazu keinen Timer/Counter, dazu reicht eine stinknormale Variable 
(mehrere Register).

...

von R. Q. (timebeast)


Lesenswert?

@Hannes:
jupp, denk ich mir auch so, einfach in einer Variable hochzählen, 
allerdings hast Du mich jetzt doch neugierig gemacht. Was meinst Du mit 
"mehrere Register"?
Ich wollte jetzt einfach im Interrupt ACI eine Variable hochzählen und 
danach mit einer anderen Variable vergleichen. Wenn gleich, dann Ziel 
erreicht.

Mit dem Timer/Counter1 wäre es halt schöner gewesen, weil der Controller 
in der Zeit wo der Counter mit den Impulsen aus dem Comparator 
beschäftigt gewesen wäre, noch andere Sachen machen hätte können. (puh, 
was für ein Deutsch, nunja)
So ist der uC halt zu 100% damit beschäftigt die Interrupts zu 
bearbeiten...naja, geht halt nicht anders, oder??

von Rahul D. (rahul)


Lesenswert?

>"mehrere Register"?

Wenn du mehr als 255 Impulse zählen willst, brauchst du mehr als ein 
Register. Mehr hat Hannes Aussage nicht zu bedeuten (meine Deutung...).

von Hannes L. (hannes)


Lesenswert?

R. Quentin wrote:
> @Hannes:
> jupp, denk ich mir auch so, einfach in einer Variable hochzählen,
> allerdings hast Du mich jetzt doch neugierig gemacht. Was meinst Du mit
> "mehrere Register"?

Wie Rahul richtig vermutete meinte ich eine Deinen Ansprüchen 
angemessene Variable von 16/24/32 Bit, also 2, 3 oder 4 Register bzw. 
RAM-Zellen.

> Ich wollte jetzt einfach im Interrupt ACI eine Variable hochzählen und
> danach mit einer anderen Variable vergleichen. Wenn gleich, dann Ziel
> erreicht.

Genau so hätte ich das auch gemacht.

>
> Mit dem Timer/Counter1 wäre es halt schöner gewesen, weil der Controller
> in der Zeit wo der Counter mit den Impulsen aus dem Comparator
> beschäftigt gewesen wäre, noch andere Sachen machen hätte können.

Das kann er doch so auch. Nehmen wir an, Dir reicht eine 16-Bit-Zahl 
(0..65535), dann muss in der AC-ISR Folgendes geschehen:

- SREG sichern (in)
- 4 Register sichern (push)
- 4 Bytes (2 für Zähler, 2 für Vergleichswert) aus SRAM holen 
(ld/ldd/lds)
- Zählerstand (mit Übertrag) erhöhen (inc, brne)
- veränderten Zählerstand im RAM sichern (st/std/sts)
- Zählerstand mit Referenz vergleichen (cp, cpc, brne)
- Jobflag für erfolgreichen Vergleich setzen (sbr)
- Register wiederherstellen (pop)
- SREG wiederherstellen (out)
- Rücksprung (reti)

In der Mainloop kann sich der Controller um andere Dinge kümmern.

Falls Deine Signale sehr langsam sind und prellen, dann solltest Du Dir 
mal die bulletproof-Entprellung von Peter Dannegger ansehen. Die findest 
Du in der Codesammlung oder im Tutorial. Sie läuft dann im 
Timer-Interrupt. Man kann damit nicht nur Tasten entprellen, sondern 
auch andere Ereignisse.


> (puh,
> was für ein Deutsch, nunja)
> So ist der uC halt zu 100% damit beschäftigt die Interrupts zu
> bearbeiten...naja, geht halt nicht anders, oder??

Doch, geht anders. Welche Methode die beste ist, kommt auf das Signal 
an. Ob allerdings ein (sauber arbeitender) "Klatsch-Schalter" so einfach 
realisierbar ist, wage ich zu bezweifeln. Ich danke, dass der 
Filteraufwand schon etwas höher sein muss, damit das Ding nicht auf alle 
anderen Geräusche anspricht.

...

von R. Q. (timebeast)


Lesenswert?

Oh Oh Oh, mist, also erstmal Danke für die Antworten. Natürlich hätte 
ich schreiben müssen für was ich das ganze brauche, ... hüstel... nein, 
ein Klatsch-Schalter ist es nicht... ;-)

Es sind die Impulse eines Inkrementalgebers einer Druckerkopf 
Positionsbestimmungs Mechanik. Also ein Plastikband mit tausenden von 
kleinen, kaum sichtbaren Strichen drauf. Wenn nun der Druckerkopf nach 
rechts/links fährt sollen diese Impulse vom uC eingelesen und mit einem 
Soll-Wert verglichen werden. (einlesen geht auch schon)

Also für´s schreiben ins Ram, obwohl sehr nette Idee, ist da wirklich 
keine Zeit.
Die Auslastung des uC kann ich noch nicht so genau sagen, muß erst noch 
experimentell bestimmt werden, da es mir unmöglich ist die Striche zu 
zählen, aber ich befürchte halt das bei höherer Geschwindigkeit ein 
Interrupt pro Takt des uC ohne Probleme zu schaffen sein wird ;-).

Sorry das ich Euch so im Dunkeln habe tappen lassen, für die 
Ausgangsfrage war die Projektbeschreibung nicht wichtig.

Aber ich denke ab hier komme ich auch wieder alleine klar. Vielen Dank 
nochmal an alle.

Gruß
Ralf

von Hannes L. (hannes)


Lesenswert?

Natürlich kannst Du auch in Registern zählen, hast ja schließlich 32 
Stück davon. Ich nehme auch erst dann RAM, wenn die Register knapp 
werden. Einige kleinere AVRs haben nichtmal RAM, da gibt's nur 32 
Register...

Hast Du eine oder zwei Lichtschranken an Deinem Strichband? Bei zwei 
könntest Du mal in der Codesammlung nach Drehgeber-Auswertung suchen, 
denn dann sind beide Signale vermutlich um 90° versetzt.

...

von Rahul D. (rahul)


Lesenswert?

>aber ich befürchte halt das bei höherer Geschwindigkeit ein
>Interrupt pro Takt des uC ohne Probleme zu schaffen sein wird ;-).

Das glaube ich kaum.
Wie schnell willst du deinen "Druckerkopf" denn bewegen?
Ich bin der Meinung, dass die Striche eine Auflösung haben, die man mit 
Hannes Methode problemlos erkennen kann. Ich kann mich aber auch 
irren...

von R. Q. (timebeast)


Lesenswert?

So, also vorweg funktionieren tut es leider noch nicht.

Erstmal Daten:
Das Strichband hat eine "Auflösung" von 60 Strichen pro cm.
Gesamte Länge ist 14cm.

Im Datenblatt des Mega8 (S.238) hab ich gefunden das die max. 
Propagation Delay bei Vcc 2,7V bei 750ns liegt. (Propagation Delay = 
Signallaufzeit ich nehm mal an das ist die Grenzfrequenz) Bei 750ns komm 
ich also auf ca 1,33MHz. Wenn man dann mal weiter rechnet müßte ich den 
Schlitten in 630us über die vollen 14cm fahren lassen. Nein, da liegt 
das Problem sicherlich nicht.

Ich Denke das das Problem in der Amplitude des Inkrementalgebers zu 
suchen ist. Der Hub von 0,5V ist doch recht wenig.

@Hannes:
jupp, es sind zwei Lichtschranken um 90° versetzt. Um die Amplitude 
(Spannung) etwas größer zu bekommen habe ich daher schon den Comparator 
des uC genommen, manchmal klappt es ja auch, aber nicht gesichert. 
Sprich, mal erkennt er mehr Impule, mal weniger.

Ich befürchte ich muß wohl noch nen OP davor basteln, der mir das Signal 
erstmal Spannungstechnisch in ein verträgliches Maß für den uC hebt.

Hab natürlich keinen da, und WE ist schon wieder, nerv...

Oder vielleicht hat ja jemand ne andere Idee wie man das Problem lösen 
könnte...

Gruß
Ralf

von Hannes L. (hannes)


Lesenswert?

R. Quentin wrote:

> Das Strichband hat eine "Auflösung" von 60 Strichen pro cm.
> Gesamte Länge ist 14cm.

Also 840 Striche insgesamt...

>
> Im Datenblatt des Mega8 (S.238) hab ich gefunden das die max.
> Propagation Delay bei Vcc 2,7V bei 750ns liegt. (Propagation Delay =
> Signallaufzeit ich nehm mal an das ist die Grenzfrequenz) Bei 750ns komm
> ich also auf ca 1,33MHz. Wenn man dann mal weiter rechnet müßte ich den
> Schlitten in 630us über die vollen 14cm fahren lassen. Nein, da liegt
> das Problem sicherlich nicht.

Das Tempo wirst Du aufgrund der Massenträgheit nicht erreichen. Wenn Du 
das (incl. Anfahren und Bremsen) in einer halben Sekunde schaffst, bist 
Du schon gut.

>
> Ich Denke das das Problem in der Amplitude des Inkrementalgebers zu
> suchen ist. Der Hub von 0,5V ist doch recht wenig.

Dann muss es eben verstärkt werden.

>
> @Hannes:
> jupp, es sind zwei Lichtschranken um 90° versetzt.

Also 2 Signale, 2 Eingänge...

> Um die Amplitude
> (Spannung) etwas größer zu bekommen habe ich daher schon den Comparator
> des uC genommen,

Es gibt aber pro AVR nur einen AC. Also muss eine andere Lösung her.

> manchmal klappt es ja auch, aber nicht gesichert.
> Sprich, mal erkennt er mehr Impule, mal weniger.

Dann solltest Du Dir die Signale mal mit einem Oszilloskop genauer 
ansehen. Damit könntest Du auch gleich die zu erwartende Signalfrequenz 
(halbwegs) ermitteln.

>
> Ich befürchte ich muß wohl noch nen OP davor basteln, der mir das Signal
> erstmal Spannungstechnisch in ein verträgliches Maß für den uC hebt.

Das wäre vermutlich eine Lösung.

>
> Hab natürlich keinen da, und WE ist schon wieder, nerv...
>
> Oder vielleicht hat ja jemand ne andere Idee wie man das Problem lösen
> könnte...

Vielleicht kannst Du die Signale ja woanders abgreifen. Denn der Rechner 
des Druckers braucht schließlich auch höhere Pegel an seinen Eingängen.

>
> Gruß
> Ralf

...

von R. Q. (timebeast)


Lesenswert?

Hannes Lux schrieb:
Es gibt aber pro AVR nur einen AC. Also muss eine andere Lösung her.

He he, ja ne, warum, ich hab einfach den einen Signalausgang auf AIN0 
und den anderen auf AIN1 gelegt.
Da die Signale ja um 90° verschoben sind, sprich wenn #1 auf High ist 
ist #2 auf Low, ergibt sich, so denke ich mir das zumindest, eine 
bessere Erkennung des Comparators des Signales, oder stimmt das so 
nicht??

Die Signale woanders abgreifen ist leider keine Option. Mehrlagen 
Platine. Ausserdem nutze ich die original Platine nicht mehr. Da war, 
besser ist, was man so sehen kann, keine OP´s verbaut, allerdings ist 
auch der Processor der verwendet wurde eine "spezial" Anfertigung. 
Sprich man findet über diesen nichts.

Die anfallenden Signale guck ich mir natürlich mit dem Oszilloskop an. 
Anders könnte ich wohl kaum sagen das das Signal eine Amplitude von 0,5V 
hat. Signalverlauf sieht gut aus, daher hab ich bisher ja auch noch auf 
einen Tiefpass verzichtet. Wie Du allerdings die zu erwartende Frequenz 
ablesen willst?? Obwohl, mit einem Speicher-Oszilloskop würde es 
wahrscheinlich gehen, tja, soviel Geld hab ich allerdings dann doch 
nicht ;-)

von Hannes L. (hannes)


Lesenswert?

R. Quentin wrote:
> He he, ja ne, warum, ich hab einfach den einen Signalausgang auf AIN0
> und den anderen auf AIN1 gelegt.

Naja, damit kannst Du aber keine Richtung erkennen und weißt daher 
nicht, ob Du incrementieren oder decrementieren musst...

> Da die Signale ja um 90° verschoben sind, sprich wenn #1 auf High ist
> ist #2 auf Low, ergibt sich, so denke ich mir das zumindest, eine
> bessere Erkennung des Comparators des Signales, oder stimmt das so
> nicht??

Ein Zyklus hat meiner Meinung nach 4 Zustände: 00, 01, 11, 10 
(Gray-Code).

> Wie Du allerdings die zu erwartende Frequenz
> ablesen willst??

Man sieht doch die ungefähre Periodendauer beim Bewegen des Druckkopfes 
anhand der Einstellung der Zeitablenkung.

> Obwohl, mit einem Speicher-Oszilloskop würde es
> wahrscheinlich gehen, tja, soviel Geld hab ich allerdings dann doch
> nicht ;-)

Ich hab' auch kein Speicheroszi. Das lässt sich auch so schätzen.

...

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.