Hallo zusammen,
ich versuche mit einem Atmega168 (16 MHz) drei ungefähr zeitgleich
ankommende CMOS Signale (CLK1-3 und DATA1-3, low-active) auf den
fallenden Flanken der CLK Leitungen auszuwerten.
Dazu habe ich CLK1 und CLK2 auf INT0 und INT1 gelegt und die
Flankenerkennung entsprechend eingestellt. Für CLK3 habe ich PCINT20
verwendet und die Flankenerkennung in der ISR geregelt. Ansonsten werden
in den entsprechenden ISR nur die Bits gesammelt.
In INT0_vect und INT1_vect erfasse ich so immer alle Bits, aber in
PCINT20 verpasse ich jedesmal mehrere Bits. Schalte ich INT0 und INT1
aber aus, dann kann ich in PCINT20 alle Bits erfassen.
Jetzt wäre meine Frage, wie ich auch zeitgleich alle drei Signale
komplett erfassen kann. Müsste ich dazu zwangsläufig auf einen Mega32
ausweichen, der ja einen zusätzlichen externen Interrupt (INT2) hat?
Oder kann ich das ganze auch mit meinem Atmega168 (INT0, INT1 und Pin
Change Interrupt) erreichen?
Anbei noch meine ISR, die ich so kurz wie möglich gehalten habe. Habe
ich da irgendwelche Fehler drin, mit denen ich mir das Timing versaue?
Vielen Dank schonmal!
Hanno
Regel 1:
Einen Interrupt kannst du nur dann verpassen, wenn durch die Abarbeitung
eines anderen Interrupts das Interrupt System lange genug gesperrt ist,
so dass zwischendurch mehrere Interrupts auflaufen können.
Das kann, durch die fixe Priorisierung auch durchaus der eigene
Interrupt sein! Tritt der nur häufig genug auf, so dass nach Beendigung
der ISR derselbe Interrupt schon wieder gefeurt hat, dann kommt keine
andere ISR mehr zum Zug.
D.h.: Feuert die Interruptquelle zu häufig (bei dir sind das dann eben
die externen Signale) dann kommt der µC nicht mehr mit. Nicht ganz
unwesentlich dabei ist dann auch, welche Arbeit in der ISR gemacht wird.
Daher die Regel: ISR so kurz wie möglich.
1
...1<<(counter_t2%TRACK2_BYTELEN)
ungünstig. variabler Bitshift ist etwas, was du deinem µC nicht
unbedingt zumuten möchtest. Ein AVR hat dafür keine Instruktionen und
muss das mit einer Schleife realisieren.
Karl Heinz Buchegger schrieb:> Einen Interrupt kannst du nur dann verpassen, wenn durch die Abarbeitung> eines anderen Interrupts das Interrupt System lange genug gesperrt ist,> so dass zwischendurch mehrere Interrupts auflaufen können.> Das kann, durch die fixe Priorisierung auch durchaus der eigene> Interrupt sein! Tritt der nur häufig genug auf, so dass nach Beendigung> der ISR derselbe Interrupt schon wieder gefeurt hat, dann kommt keine> andere ISR mehr zum Zug.
Vielen Dank für die Antwort. Meine Befürchtung war eigentlich nicht,
dass ich einen Interrupt verpasse, sondern eher, dass der Interrupt zu
spät abgearbeitet wird und auf der Datenleitung längst ein anderer
Zustand herrscht. Der Threadtitel war wohl ungünstig gewählt.
Zu dem Bitshift: Also sollte ich die Bits mit "vorberechneten" Masken
reinodern??
Die drei CMOS Signale kommen von einem Magnetkartenleser von Pollin
(ZU-M1363S1E1). Interessanterweise kann ich mit meinem Code Track1 und
Track2 (über INT0 und INT1) gleichzeitig problemlos auslesen. Wenn ich
aber Track1 ausschalte und Track2+Track3 gleichzeitig lesen will, dann
klappts nichtmehr: Fehler in Track3 (PCINT20), während Track2
einwandfrei gelesen wird. Daher auch meine Verwirrung, denn mein ISR
Code scheint ja nicht zu komplex zu sein, sonst könnte ich Track1+Track2
ja nicht gleichzeitig fehlerfrei erfassen?!
Hanno H. schrieb:>> der ISR derselbe Interrupt schon wieder gefeurt hat, dann kommt keine>> andere ISR mehr zum Zug.>> Vielen Dank für die Antwort. Meine Befürchtung war eigentlich nicht,> dass ich einen Interrupt verpasse, sondern eher, dass der Interrupt zu> spät abgearbeitet wird und auf der Datenleitung längst ein anderer> Zustand herrscht.
Das kannst aber nur du wissen!
Denn nur du weißt, wie sich das Timing deiner Signale gestaltet.
> Zu dem Bitshift: Also sollte ich die Bits mit "vorberechneten" Masken> reinodern??
Wär eine Möglichkeit.
> Die drei CMOS Signale kommen von einem Magnetkartenleser von> Pollin (ZU-M1363S1E1).
Und mit welcher Frequenz taktest du deinen µC? Wie hoch ist die Frequenz
der Signale vom Leser?
Hast du dir denn schon mal deine Signale am Oszi angesehen. Immerhin
wäre ja auch die Umkehrung denkbar: Dass das Datensignal mit der
Clockflanke noch nicht stabil genug anliegt und du tatsächlich zu früh
drann bist.
Im übrigen denke ich nicht, dass du mit derartigen Spielchen "diesen
Interrupt aktivieren, jenen nicht) in irgendeiner Form weiterkommst. Die
Aussagekraft derartiger Kombinationsspielchen ist meistens sehr gering.
H. H. schrieb:> Meine Befürchtung war eigentlich nicht,> dass ich einen Interrupt verpasse, sondern eher, dass der Interrupt zu> spät abgearbeitet wird und auf der Datenleitung längst ein anderer> Zustand herrscht.
Oder Clock wieder zurückgewechselt ist und das ganze als "Fehlalarm"
interpretiert wird.
Mach doch Kanal 2 an den PinChange. Der Kanal 2 hat laut DB ne
niedrigere Datendichte.
Karl Heinz Buchegger schrieb:> Hanno H. schrieb:>>>> der ISR derselbe Interrupt schon wieder gefeurt hat, dann kommt keine>>> andere ISR mehr zum Zug.>>>> Vielen Dank für die Antwort. Meine Befürchtung war eigentlich nicht,>> dass ich einen Interrupt verpasse, sondern eher, dass der Interrupt zu>> spät abgearbeitet wird und auf der Datenleitung längst ein anderer>> Zustand herrscht.>> Das kannst aber nur du wissen!> Denn nur du weißt, wie sich das Timing deiner Signale gestaltet.>>>> Zu dem Bitshift: Also sollte ich die Bits mit "vorberechneten" Masken>> reinodern??>> Wär eine Möglichkeit.
Habs gerade mit fertigen Masken probiert, leider keine Verbesserung.
>> Die drei CMOS Signale kommen von einem Magnetkartenleser von>> Pollin (ZU-M1363S1E1).>> Und mit welcher Frequenz taktest du deinen µC?
Mit einem 16 MHz Quarz (CKDIV8 habe ich natürlich ausgenommen :).
> Hast du dir denn schon mal deine Signale am Oszi angesehen. Immerhin> wäre ja auch die Umkehrung denkbar: Dass das Datensignal mit der> Clockflanke noch nicht stabil genug anliegt und du tatsächlich zu früh> drann bist.
Ein Oszilloskop habe ich leider nicht zur Verfügung. Ich habe aber auch
mal testweise 1-200 µs gewartet, bevor ich auf die Datenleitung geschaut
habe. Aber da kam nur Mist raus. Eigentlich kann ich mit meinem µC auch
nicht zu früh dran sein, denn ohne INT0/1, also nur mit PCINT20 für
Track3 komme ich super hin und erwische alle Bits.
Stephan schrieb:> Mach doch Kanal 2 an den PinChange. Der Kanal 2 hat laut DB ne> niedrigere Datendichte.
@Stephan
Weißt du, über welche Frequenzen wir hier reden?
Der TO scheint das ja nicht zu wissen und ich bin es mitlerweile leid,
da ins Blaue zu raten, wie eng (zeitlich gesehen) die ganze Geschichte
wirklich ist.
Wenn das irgendwie genau werden soll, so sollten die 3 Kanäle gesampelt
werden. D.h. drei FFs speichern den Zustand der Leitungen in
Abhängigkeit der verschiedenen Flankenwechsel.
Mit Verzögerungen über INT-Eingänge und dem Lesen der anderen Leitungen
ist die Aussagekraft der Messung komplett weg. Da kannst Du gleich
raten.
Wenn ichs richtig verstanden habe, willst Du einen Logiganalyser mit
großem Speicher, aber geringen Kosten. Wenn die Messergebnisse wichtig
sein sollten, dann kauf Dir sowas. Alles andere wird ein unsicheres
Gebastel.
Karl Heinz Buchegger schrieb:> Weißt du, über welche Frequenzen wir hier reden?> Der TO scheint das ja nicht zu wissen und ich bin es mitlerweile leid,> da ins Blaue zu raten, wie eng (zeitlich gesehen) die ganze Geschichte> wirklich ist.
Bitte entschuldige! Im folgenden Frequenzbereich kommen die Signale an:
290 bis 9950 Hz (in Abhängigkeit von der Kartengeschwindigkeit beim
Durchziehen und der Datendichte der Tracks).
@Stephan: Den Wechsel werde ich ausprobieren, vielen Dank schonmal.
Hanno H. schrieb:> Bitte entschuldige! Im folgenden Frequenzbereich kommen die Signale an:> 290 bis 9950 Hz (in Abhängigkeit von der Kartengeschwindigkeit beim> Durchziehen und der Datendichte der Tracks).
Also 1K
Dann brauchst du dir um Timing keine Sorgen machen. Das ist für deinen
µC Superzeitlupe.
Also muss dein Problem wo anders liegen.
Kann es sein, dass das Clock Signal nicht sauber ist und dir den
Interrupt mehrfach triggert?
(Bei diesen Frequenzen würd ich überhaupt nicht mit Interrupts
rummachen, sondern auf Polling setzen. Timer aufsetzen, der in seiner
ISR mit Hausnummer 5kHz die Eingänge überwacht und bei Flankendetektion
den jeweiligen Zustand feststellt)
Wieder mal großes Rätselraten:
Welchen Typ haben track1, track2, track3?
Welchen Typ haben counter_t1, counter_t2, counter_t1?
Welchen Wert haben TRACK1_BYTELEN, TRACK2_BYTELEN, TRACK3_BYTELEN?
Warum liest Du in PCINT2_vect überhaupt DATA3 aus, wenn Du diesen dann
wegen falscher Flanke auf CLK3 ignorierst?
spess53 schrieb:> Hi>>>Also 1K>> Eher 10k.>> MfG Spess
Ähm.
Wie war das mit der Stirn und der Tischkante. Muss ich gleich mal
ausprobieren.
Ok, dann nehm ich die Superzeitlupe zurück und ersetze durch Zeitlupe.
Hanno H. schrieb:> Im folgenden Frequenzbereich kommen die Signale an:> 290 bis 9950 Hz
Kommt hin. Datenblatt ist ggf. hier:
http://www.pollin.de/shop/downloads/D721519D.PDF>1000 Instruktionen auf 3 Interruptroutinen sollten aber eigentlich mehr als genug
Reserve sein. Auch mit ungünstigem Code.
Nach dem Timing-Diagramm sollten mindestens 25 µs nach dem Clock-Signal
auch noch korrekt ausgelesen werden können.
Kann auch sein, dass er einen Buffer-Overflow hat, der nur bei
Aktivieren von DATA3 zum Tragen kommt, weil track3 bis dahin als
zusätzliche Pufferzone für track1 und track2 dient... denn es fehlt in
den ISRs jeglicher Check auf Überlauf der Arrays.
Hat keinen Sinn, da weiter zu raten. Ohne vollständigen Quellcode ist
alles reine Spekulation.
Wenn ich mir das Datenblatt zu dem Magenetkarten-Reader bei Pollin
anschaue, haben die TRACKx_BYTELEN den Wert 5. Nicht gerade günstig für
Division und Modulo-Operator. Da wäre es besser, jeweils einen Bit- und
einen Bytezähler mitzuführen, um den Index und das Bit im Array zu
bestimmen, welches gesetzt werden muss.
@Karl:
Danke, ich werde es mal mit Polling versuchen. Aber aus Interesse: Wie
könnte ich rausfinden, ob das CLK Signal unsauber ist (ohne Oszi)?
@Frank:
Die Datentypen habe ich absichtlich nicht eingefügt. Der Code tut ja
das, was er soll - es war nur die Frage ob er es auch schnell genug tut
(ist ja mittlerweile geklärt :). Habe ich jetzt angehängt.
Das Auslesen habe ich beim Ausprobieren testweise vor die
Flankendetektion geschrieben, da ich möglichst "schnell" sein wollte.
(Jaja, das war Käse.)
Einen Buffer Overflow habe ich nicht, die sind groß genug gewählt. Das
konnte ich im Debugger sehen. Natürlich gehört in den ISR noch ein Check
rein, aber aus meiner (falschen) Befürchtung zu langsam zu sein, habe
ich alles an Code entfernt, was nicht absolut nötig ist.
Den Einwand mit den Operatoren verstehe ich nicht? Ich brauche nur die
Anzahl der gelesenen Bits und kann mit DIV und MOD bestimmen wo das
nächste Bit hin muss. Ich schreibe jeweils 7 bzw. 5 Bits in ein Byte,
weil ich es so später bequem in ASCII dekodieren kann.
@MWS:
Nope, im Register ist nur PCINT20 angeknipst.
Nochmal Danke an alle, für eure Hilfe :)
Hanno H. schrieb:> Einen Buffer Overflow habe ich nicht, die sind groß genug gewählt.
Nicht, wenn ein CLK-Signal "unsauber" ist und zum Beispiel "prellt". Ich
empfehle Dir, den Check auf jeden Fall einzubauen.
> Den Einwand mit den Operatoren verstehe ich nicht? Ich brauche nur die> Anzahl der gelesenen Bits und kann mit DIV und MOD bestimmen wo das> nächste Bit hin muss. Ich schreibe jeweils 7 bzw. 5 Bits in ein Byte,> weil ich es so später bequem in ASCII dekodieren kann.
Eine Division/Modulo-Operation mit 8 oder einer anderen Zweierpotenz ist
wesentlich schneller als mit 5 oder 7, da der Compiler hier einfach Bits
schieben kann. Das kostet ordentlich, was Du da machst. Deshalb mein
Vorschlag, zwei Counter zu verwenden: einen für den Index (Bytecounter)
und einen für die Bits (Bitcounter), welche Du nach Erreichen von von
TRACKx_BYTELEN wieder zurücksetzt, um dann den Bytecounter zu
inkrementieren. Das spart sowohl eine Division als auch den
Modulo-Operator komplett ein.
> uint16_t counter_t1 = 0;> uint16_t counter_t2 = 0;> uint16_t counter_t3 = 0;
Wenn Du diese außerhalb der ISRs auch verwendest, müssen sie volatile
deklariert sein. Wenn sie ausschließlich in den ISRs verwendet werden,
gehören sie als static Variablen in die ISRs. Das gleiche gilt für die
Arrays selbst. Sonst kommt da evtl. Mist raus.
Gruß,
Frank
Hanno H. schrieb:> @Karl:> Danke, ich werde es mal mit Polling versuchen. Aber aus Interesse: Wie> könnte ich rausfinden, ob das CLK Signal unsauber ist (ohne Oszi)?
Ohne Oszi ist natürlich schwer.
Ich würd da mal hinterher die counter ansehen, ob die plausibel sind.
Frank M. schrieb:> Nicht, wenn ein CLK-Signal "unsauber" ist und zum Beispiel "prellt". Ich> empfehle Dir, den Check auf jeden Fall einzubauen.
Ja, der Check wird auch eingebaut. Aber wenn die CLK Line prellt, dann
sind die gesammelten Bits sowieso für die Katz (und ein BO wäre mir bei
Testzwecken mehr oder minder egal).
> Eine Division/Modulo-Operation mit 8 oder einer anderen Zweierpotenz ist> wesentlich schneller als mit 5 oder 7, da der Compiler hier einfach Bits> schieben kann. Das kostet ordentlich, was Du da machst. Deshalb mein> Vorschlag, zwei Counter zu verwenden: einen für den Index (Bytecounter)> und einen für die Bits (Bitcounter), welche Du nach Erreichen von von> TRACKx_BYTELEN wieder zurücksetzt, um dann den Bytecounter zu> inkrementieren. Das spart sowohl eine Division als auch den> Modulo-Operator komplett ein.
Das klingt sinnvoll, sofern die beiden Counter dann als Register und
nicht im RAM vorliegen. Wäre sicher eine weitere Optimierung, aber ist
wohl nicht ursächlich für mein Problem (Timing wurde ja ausgeschlossen).
Also falls noch jemand Ideen hat, wie ich eine prellende CLK Line
feststellen und beheben könnte (ohne Oszi) oder sonst noch Anregungen
hat, bin ich immer offen :)
Hanno H. schrieb:> Die Datentypen habe ich absichtlich nicht eingefügt. Der Code tut ja> das, was er soll - es war nur die Frage ob er es auch schnell genug tut> (ist ja mittlerweile geklärt :).
Ich denke: schnell genug wird es schon noch sein.
Aber mit Bit/Bytezählern bzw. entsprechenden Masken entlastest du deine
ISR ungeschaut um einen Faktor 8 bis 10 (wenn nicht noch mehr. Sind ja
schliesslich Division und Modulo)
(Ich wusste bisher nicht, dass da keine 2-er Potenzen im SPiel sind,
drum hab ich weiter oben "ja" zu einem Maskenarray gesagt. Aber so ist
das für den µC noch viel simpler.
Hanno H. schrieb:> Also falls noch jemand Ideen hat, [...]
Du hast Dich leider nicht zur volatile-Deklaration Deiner in dne ISRs
benutzten Variablen geäußert. Das könnte bei Dir schon das Problem
beseitigen. Ja, volatile ist hier zwingend notwendig.
Karl Heinz Buchegger schrieb:> (Ich wusste bisher nicht, dass da keine 2-er Potenzen im SPiel sind,> drum hab ich weiter oben "ja" zu einem Maskenarray gesagt. Aber so ist> das für den µC noch viel simpler.
Tja, wie so oft: Der TO lässt für ihn unwichtig erscheinende Infos
(sogar bewusst) weg, die sich aber im nachhinein als durchaus
ausschlaggebend für das Problem entpuppen können.
Frank M. schrieb:> Tja, wie so oft: Der TO lässt für ihn unwichtig erscheinende Infos> (sogar bewusst) weg, die sich aber im nachhinein als durchaus> ausschlaggebend für das Problem entpuppen können.
War keine Absicht. Hatte den Überblick verloren. Jedenfalls ist es mit
als volatile deklarierten Variablen auch nicht gelöst.
In die ISR habe ich jetzt einen zweiten Counter (temp_count) eingefügt,
um die CLK Line zu beobachten. Dabei ist mir aufgefallen, dass
counter_t3 nicht genau halb so groß ist wie temp_count, sondern um
5-10 abweicht. Das würde ja für eine prellende CLK Leitung sprechen,
oder?
(Wenn ich allerdings nur Track3 lese, dann ist counter_t3 immer exakt
die Hälfte von temp_count.)
Hanno H. schrieb:> um die CLK Line zu beobachten. Dabei ist mir aufgefallen, dass> counter_t3 nicht genau halb so groß ist wie temp_count, sondern um> 5-10 abweicht.
größer oder kleiner?
Hast du zuviele Pulse oder zu wenige gezählt?
Karl Heinz Buchegger schrieb:> Hanno H. schrieb:>>> um die CLK Line zu beobachten. Dabei ist mir aufgefallen, dass>> counter_t3 nicht genau halb so groß ist wie temp_count, sondern um>> 5-10 abweicht.>> größer oder kleiner?> Hast du zuviele Pulse oder zu wenige gezählt?
Also bei den fehlerhaften Swipes ist 2*counter_t3 < temp_count mit einer
Differenz von 5-10. Bei guten Swipes ist 2*counter_t3 == temp_count.
1
vier fehlerhafte Swipes:
2
Swipe 1. 2. 3. 4.
3
tmp 0x569 0x56b 0x569 0x56b
4
t3 0x2b0 0x2b1 0x2b0 0x2b3
5
6
zwei "gute" Swipes wo ich nur Track3 lese:
7
Swipe 1. 2.
8
tmp 0x570 0x536
9
t3 0x2b8 0x29b
Deinen Code habe ich eingefügt. Allerdings wurde dadurch auch das
Problem nicht behoben.
Nochmals Danke an alle! :)