Forum: Mikrocontroller und Digitale Elektronik AVR Assembler Interrupts zählen


von Paul F. (nixverstehikus)


Angehängte Dateien:

Lesenswert?

Hallo,

ich verfolge das mittelfristige Ziel irgendwann einmal einen normalen DC 
Motor als Servo zu betreiben indem ich an der Motorwelle eine 
Lochscheibe (oder etwas ähnliches) befestige und die Impulse einer 
Gabellichtschranke beim drehen der Lochscheibe zähle.

Bevor ich das ganze mit Motor und Gabellichtschranke realisiere wollte 
ich erstmal die Impulse eines mechanischen Schalters zählen.
Ich habe nun ein halbfertiges Assembler Programm genommen und versucht 
das ganz so anzupassen das die Zählfunktion tut. Meine Idee war das wenn 
ein Interrupt 8 Mal gedrückt wird eine LED aufleuchten soll.

Leider funktioniert es nicht und ich weiß nicht warum.

Wäre super wenn Ihr mir weiterhelfen könntet.

Grüße
nixverstehikus

von Oldie (Gast)


Lesenswert?

Wenn du r16 "hochzählst",
wozu dann der Vergleich von r18 mit einem Festwert?

Außerdem solltest du bei "bam:" auch r16/18 (entscheide
dich!) wieder auf NULL setzen, damit es nicht erst nach
weiteren 256 Interrupts wieder funktioniert...

Eventuell könnte auch Entprellen (bei Tastern, oder Relais-
kontakten) noch zum Thema werden...

von Lilalaunebaer (Gast)


Lesenswert?

...Du incrementierst r16 und prüfst r18 ?

von Paul F. (nixverstehikus)


Lesenswert?

Hallo,
danke für eure Antworten.
Hab mich im Code nun für ein Register entschieden ;-) und es tut.

Grüße
Paul

von Sebastian S. (amateur)


Lesenswert?

Gewöhn' Dir doch möglichst bald, Interruptroutinen die nichts sichern, 
ab.

von Paul F. (Gast)


Lesenswert?

Hallo Sebastian,

wie würdest du so ein zählen von "Flankenwechseln" realisieren.
Mit der Interruptroutine zählt er sauber mit ohne das man das Signal 
entprellen muss.

Wie macht man das für gewöhnlich wenn man die Motorposition über eine 
Gabellichtschranke mit Lochscheibe ermitteln möchte.
Theoretisch dürfte es bei der Gabellichtschranke immer nur dann 
mitzählen wenn es einen Flankenwechsel gibt.

Wäre das nicht sauberer gelöst wie über polling?

Grüße
Paul

von Dr. Sommer (Gast)


Lesenswert?

Schlauer ist es, mithilfe des Input Capture des Timers, die Länge der 
Pulse zu messen. So erhält man schneller eine Information über die 
Drehzahl. Das setzt natürlich eine genau gefertigte Lochscheibe vorraus.

von Sebastian S. (amateur)


Lesenswert?

Über das wann oder wann nicht in Sachen: Polling vs. Interrupt wurden 
bereits ganze Bücher veröffentlicht.

Ich bin der Meinung: Kommt drauf an. Beides hat seine 
Daseinsberechtigung.

Willst Du nur "Löcher/Schlitze" zählen, so sollten ein Schmitt-Trigger 
oder ein Eingang, der auf Flankenwechsel reagiert, ausreichen.

Im Normalfall brauchst Du Dir keine Gedanken über ein eventuelles 
Prellen machen. Prellen ist die Domäne der Schalter und Taster.

Dumm ist nur, dass man den Normalfall nicht gleich miteinbauen kann.

Bei Deiner Anwendung kommt das Problem: Was ist beim Stillstand, an 
einer Grenze angesagt? Was ist bei - in mechanischen Anwendungen normal 
- Vibrationen möglich?

Also Flankenwechsel erfassen, am besten zusammen mit der Zeit und dann, 
im Falle eines Falles, über die Zeit eine Plausibilitätsprüfung 
durchführen.
Da mechanische bzw. rotierende Massen keine Sprünge machen können, 
lassen sich einige Fehler auf diese Weise eliminieren. Also 
"Zwischenschritte" durch Staub im System. Extrem hohe Impulsfolgen durch 
Vibrationen im Stillstand an der Hell-Dunkel-Grenze.

Viele dieser Überprüfungen sind, bei der heutigen Rechenleistung der 
µC‘s kein Problem. Allerdings kann man es auch übertreiben und den 
Rechner damit abwürgen.

Vergiss aber eine kleine Beschränkung nicht: Eine "normale" 
Loch-/Schlitzscheibe ist demokratisch. Sie arbeitet in beiden Richtungen 
(rinks und lechts) gleichermaßen.

von Peter D. (peda)


Lesenswert?

Paul F. schrieb:
> Hab mich im Code nun für ein Register entschieden ;-)

Man kann Registern und Portpins beschreibende Namen geben, damit man 
solche Fehler vermeidet und überhaupt selber später noch durchsieht.

: Bearbeitet durch User
von Paul (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe nun den im Anhang befindenden Code zusammengestellt um meine 
Interrupts zu zählen.

Interrupt 0 (über mechanischen Druckschalter aktiviert) soll dafür 
sorgen das BIT 0 von PORTB angeht (bzw. die Diode die am Port hängt) 
sobald die Taste zum erstenmal gedrückt wurde. Wird Interrupt0 4 mal 
gedrückt soll auch die Diode an Bit 1 von PORTB angehen.

Mit dem Interrupt 1 (über mechanischen Druckschalter aktiviert) sollen 
beide DIODEN am PORTB wieder erlischen.

Gefühlt funktioniert nur der Interrupt1 richtig.
Interrupt0 läuft irgendwie willkürlich. Irgendwann gehen die Dioden halt 
an.
Ich als Anfänger kanns mir im Moment nicht erklären wieso das so ist.
Veilleicht kann mir einer von euch weiterhelfen.....
Ich glaube nicht das es was mit dem Entprellen zu tun hat denn wie 
gesagt Interuppt 1 geht eigentlich immer.

Danke im Voraus

Grüße
Paul

von kalaus (Gast)


Lesenswert?

wenn r17 mal auf 4 ist, wird es dann auch wieder zurückgesetzt, damit es 
wieder bis 4 zählen kann?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Paul schrieb:
> Ich glaube nicht das es was mit dem Entprellen zu tun hat denn wie
> gesagt Interuppt 1 geht eigentlich immer.

 a) Nur INT0 ist auf fallende Flanke, INT1 ist auf low level gesetzt.
 b) r17 wird niemals zurückgesetzt, wahrscheinlich werden die Dioden
   in INT0 einmal eingeschaltet, aber durch Tastenprellen auch gleich
   wieder in INT1 ausgemacht.

 PROBE:
 Setze einen Flag in INT0, in mainloop Flag prufen, wenn gesetzt, 40ms
 Int's sperren, danach Flag zurucksetzen, sei, usw.
 Wenn's funktionert, richtig codieren.

: Bearbeitet durch User
von Nixverstehikus (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich stehe immer noch vor der Herausforderung das Programm laufen zu 
lassen.
Ich habe mittlerweile eine Warteschleife für das Entprellen der Taster 
eingefügt. Trotzdem funktioniert das Programm nicht. Hat mir jemand den 
Hinweis warum das so ist?

Grüße
Nixverstehikus

von Marc V. (Firma: Vescomp) (logarithmus)


Angehängte Dateien:

Lesenswert?

Nixverstehikus schrieb:
> Ich habe mittlerweile eine Warteschleife für das Entprellen der Taster
> eingefügt. Trotzdem funktioniert das Programm nicht. Hat mir jemand den
> Hinweis warum das so ist?

 Weil es verkehrt ist.
 Bei INT1 ist es absolut egal, ob der Taster prellt oder nicht, deswegen
 funktioniert das ausschalten der LEDs.
 Bei INT0 wird bei jedem Eintritt ein Delay von etwa 20us (glaube ich)
 aufgerufen, nach 4 Aufrufen wird LED2 eingeschaltet.
 Das ist aber:
  a) bei weitem zu kurz, alle 4 Abfragen werden gemacht während
     dein Taster noch prellt.
  b) Delays macht man unter keinen Umständen in der ISR, sondern
     ausserhalb. Ausnahmen sind nur wirklich notwendige Delays von
     weniger als 5-10us.

 Ich habe versucht, dir ein Programm zu schreiben, das einerseits
 leicht zu verstehen ist und andererseits erweitert werden kann.
 Das geht natürlich nicht mit diesem Programm, um Taster die mit
 INT-Routinen arbeiten zu entprellen, wirst du um eine Timer Routine
 nicht herumkommen.
 Probiere aber erstmal das angehängte Programm.

 P.S.
 Sowohl in der INT0 als auch in der INT1 Routine wird weder SREG noch
 andere Register gerettet, es ist nur zum Probieren, könnte aber
 evtl. beim _Wms und anderen Vergleichen in die Hose gehen.

: Bearbeitet durch User
von Uwe (Gast)


Lesenswert?

Hi,
@Marc Vesely
Dein Programm geht davon aus das Taster immer prellen, dem ist aber 
nicht immer so(ich habe solche Taster). Für den Fall brauchst du viel 
Kaffee oder besser, das Ganze wird ein Reaktionstester ;)

>LichtAus:  cbi  PORTB, 0
>    cbi  PORTB, 1
>    clr  rPrell      ;* Flags loeschen
>    clr  rCnt      ;* Zaehler fuer Tastendruecke loeschen
>    reti        ;* Rückkehr zum Hauptprogramm
Das halte ich für gewagt. 1 Fehlimpuls und die Sache ist gegessen.

Viel Erfolg, Uwe

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Uwe schrieb:
> Dein Programm geht davon aus das Taster immer prellen, dem ist aber
> nicht immer so(ich habe solche Taster). Für den Fall brauchst du viel
> Kaffee oder besser, das Ganze wird ein Reaktionstester ;)

 Sorry, verstehe ich nicht.

> Das halte ich für gewagt. 1 Fehlimpuls und die Sache ist gegessen.

 Und das verstehe ich noch weniger...

 Kannst du mich bitte aufklären ?

von Uwe (Gast)


Lesenswert?

Hi,

>>Dein Programm geht davon aus das Taster immer prellen
>Sorry, verstehe ich nicht.
Ok, das nehme ich zurück weil du ja bei der 1, Flanke schon hochzählst.
Das hatte ich übersehen weil ich Signale erst verarbeite wenn sie
"sauber stehen".
Es hat aber einen andere Nebenwirkung: fehlerhafte Einzelimpulse werden 
auch gezählt wenn sie nur mit dem nötigen Abstand kommen.

 "LichtAus" ist doch auch ein Int. oder nicht?
Wenn ja, reicht ebenfalls ein Fehlimpuls um PORTB, 1 zu löschen.

oder ich habe einen kompletten Denkfehler.

Viel Erfolg, Uwe

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Uwe schrieb:
> Wenn ja, reicht ebenfalls ein Fehlimpuls um PORTB, 1 zu löschen.

> Es hat aber einen andere Nebenwirkung: fehlerhafte Einzelimpulse werden
> auch gezählt wenn sie nur mit dem nötigen Abstand kommen.

 Was meinst du dauernd mit Fehlimpuls ?
 Der TO soll nur probieren, ob es mit diesem Programm klappt, deswegen
 werden LEDs in der ISR sowohl ein- als auch ausgeschaltet.
 Feinheiten wie z.B. prüfen auf Zustand kommen erst vieeel später...

von Uwe (Gast)


Lesenswert?

Hi,
>Feinheiten wie z.B. prüfen auf Zustand kommen erst vieeel später...
oha, da habe ich wohl was falsch verstanden, dachte eigentlich du willst 
die Grunlagen des Entprellens rüberbringen.

viel Erfol, Uwe

von Nixverstehikus (Gast)


Lesenswert?

Hallo,

danke für eure Antworten.
Vorallem für den Code.
Ich hätte hierzu noch eine Frage.

ldi  zl, cmsPrell    ;* Definierte PrellZeit in ms die der uC warten 
rcall  _Wms


Darf man den Befehl so ausführen ohne z1 vorher zu definieren?
Der Compiler hat nicht gemeckert...

Grüße
Nixverstehikus

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Nixverstehikus schrieb:
> Darf man den Befehl so ausführen ohne z1 vorher zu definieren?

 Wie definieren ?
 Falls du Register meinst, zl ist schon als Register definiert.
 Es ist r30.

: Bearbeitet durch User
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.