Hier nochmal die Routine dazu:
In der Pchg_isr werden alle Pegelwechsel innerhalb einer Timerperiode
gesammelt und das jeweilige Bit in "Changed_pins_sum" gesetzt. Eine 1
bedeutet hierbei, dass sich dieses Bit verändert hat, nicht jedoch, dass
sein Pegel 1 ist...!
In der Timer_Isr wird der letze PINB-Status nach "Deb_pinb"
transferiert,
wobei das Byte in "Changed_pins_sum" die Maske liefert, für jene Bits
(die
gekippten) die beim Übertrag nach "Deb_pinb" ausgelassen werden.
Kurz: 'Wd_isr' ist eine Transferroutine von Byte A nach Byte C, wobei
das
Bitmuster im Masken-Byte B (hier das "Changed_pins_sum") bestimmt,
welche Bits im Zielbyte unverändert bleiben sollen.
Die gesamte Routine sollte somit geeignet sein, abhängig vom
Timerintervall, eine reproduzierbare Grenzfrequenz zu realisieren, indem
sie die präzise erfassten Flankenwechsel die in kürzerer Periode als
Tim_int eintreffen, nicht weiterleitet.
Die Codelaufzeit in Zusammenhang mit dem Systemtakt muss dabei natürlich
mit einbezogen werden.
'******************************************
.
Last_pins_state = Pinb
.
.
Do
.
Loop
.
.
'*********************
Pchg_isr:
1 Changed_pins = Last_pins_state Xor Pinb
2 Last_pins_state = Pinb
3 Changed_pins_sum = Changed_pins_sum Or Changed_pins
Return
'********************
Wd_isr:
4 If Changed_pins_sum = 0 Then
5 Deb_pinb = Last_pins_state
6 Else
7 Deb_pinb = Deb_pinb And Changed_pins_sum
8 Changed_pins_sum = Changed_pins_sum Xor &HFF
9 Changed_pins_sum = Changed_pins_sum And Last_pins_state
10 Deb_pinb = Deb_pinb Or Changed_pins_sum
11 Changed_pins_sum = 0
12 End If
Return
' bei 8,9 u.10 wird "Changed_pins_sum" nur noch als Temp-Variable
'mißbraucht' bzw. 'recycled', ohne inhaltlichen Bezug zu ihrem
anfänglichen Namen.
Mike
Was mich noch interessieren würde:
Kann man diese Art der Maskierung (Protektion der Zielbits mittels
Maske) mit anderen Operationen schneller, und/oder kürzer realisieren..?
Michael Schurr schrieb:> Was mich noch interessieren würde:>> Kann man diese Art der Maskierung (Protektion der Zielbits mittels> Maske) mit anderen Operationen schneller, und/oder kürzer realisieren..?
Nein.
Ok. In BASCOM vielleicht nicht, aber ein C-Compiler macht aus deinem
Code
2 Ladeinstruktionen
2 And
1 XOR
1 Or
1 Speicherinstruktion
alles in allem 7 Taktzyklen, wovon 3 nicht optimierbar sind (Laden und
Speichern)
Was willst du da noch groß optimieren?
Du optimierst an der falschen Stelle. Ob der Timer Interrupt jetzt 0.5
Promille oder 0.5001 Promille der Rechenzeit braucht, ist sowas von
Wurscht. Wenn dieser Unterschied in deinem Progamm einen Unterschied
macht, dann hast du ganz andere Probleme.
Sorg lieber dafür, dass deine Tastendruck-Auswertung ordentlich
benutzbar wird. Da hast du mehr davon. Denn bis jetzt hast du ja nur
einen Tastenzustand aber noch keine Erkennung eines einzelnen
Tastendrucks.
Man muß auch berücksichtigen, daß jeder Interrupt ein Prolog/Epilog
Gedöns braucht. Beim AVR-GCC gehen dafür allein gerne mal 30..40 Zyklen
drauf.
Wenn also der ICP-Interrupt keinen großen Vorteil bringt, kostet er
trotzdem zusätzlich.
Hi Kh,
nein das ist jetzt nicht akut relevant. Wollte nur generell von der
Profiseite her wissen, ob es da elegantere und schnellere Lösungen gibt.
Und generell will man schon immer Zeit und Platz von vornherein sparen.
Nachher ist es immer etwas mühselig, wenn es klemmt. Vor allem sind
knappe und sporadische Timingprobleme nicht Debugger's Lieblingshobby...
;-)
Michael Schurr schrieb:> Und generell will man schon immer Zeit und Platz von vornherein sparen.
Ja das kenn ich.
Ich sitz auch an so einem Programm an dem ein einzelner 15 Jahre lang
jegliche softwaretechnische Sorgfalt hat missen lassen und gnadenlos
optimiert hat - Funktionsaufrufe kosten ja auch so viiieel Zeit.
Das Ergebnis vom Lied:
Er ist nicht mehr in der Firma und 5 Mann arbeiten seit ca 2 Jahren
daran, wenigstens die gröbsten Softwaresünden und schlimmsten Bugs
auszumerzen. Während nebenbei auch noch die Weiterentwicklung laufen
soll.
Aber Hauptsache das Programm ist schnell .... manchmal sind die
Ergebnisse zwar, sagen wir mal, kreativ aber die sind dafür dann auch
schnell da.
Das Hauptaugenmerk eines Profis liegt auf wartbarem Code! Und nicht auf
der Optimierung des letzten Taktzykluses. "Schnell genug" ist völlig
ausreichend. Mehr braucht es nicht.
Hab die Routine nochmal optimiert, so daß jetzt auch bei Mehrfachprellen
innerhalb des aktuellen Timerintervalls nur ein einziger Pchg-Int pro
Eingang auftritt.
Eine weitere Optimierung (Code in Klammern) ist noch dadurch möglich,
daß bei statischen (ruhigen) Eingängen, auch noch der Timer_Int
deaktiviert wird, falls dieser nicht auch von anderen Routinen genutzt
wird.
Die ganze Debounce-Routine ist somit bei ruhigen Eingängen total inaktiv
und verbraucht keinerlei Zeit durch Prüfroutinen und Ints mit
Push/Pop-Sequenzen. Sie wird nur bei einem neuerlichen Pegelwechsel für
einen(!) Durchlauf aktiviert.
Das bedeutet maximale Treffsicherheit bei Erkennung von Prell-, oder
Störimpulsen, bei maximaler Zeiteffizienz.
Die hier oft credomässig postulierte Behauptung, daß Pchg-Int bei der
Tastenentprellung nichts zu suchen hat, ist so gesehen nicht
überzeugend. Die Vorteile überwiegen bei Weitem, wenn es richtig
umgesetzt ist. Selbst die Int-Aufrufe und die beanspruchte Gesamtzeit,
liegen mit der jetzigen Implementierung hinter denen, die bei einer
ununterbrochenen, zyklischen Pollingaktivität auch ohne jegliche
Tastenaktivität verbraten werden.
....
'Init:
.
.
Pcmsk=&b00010111 'Pchg_Int_Maske
Pcmsk_copy = Pcmsk
Last_pins_state = Pinb
'Main:
.
do
...
loop
.
'ISRs:
'*********************
Pchg_isr:
(Set WDIE => WDTimer_Int enablen)
Changed_pins = Last_pins_state XOR Pinb
Last_pins_state = Pinb
Changed_pins_sum = Changed_pins_sum OR Changed_pins
Stable_pins = Changed_pins_sum XOR &HFF
Pcmsk = Pcmsk AND Stable_pins
Return
'*****************
Wd_isr:
If Changed_pins_sum = 0 Then
Deb_pinb = Last_pins_state
(Reset WDIE => WDTimer_Int disablen)
Else
Deb_pinb = Deb_pinb AND Changed_pins_sum
Stable_pins = Stable_pins AND Last_pins_state
Deb_pinb = Deb_pinb OR Stable_pins
Changed_pins_sum = 0
End If
Pcmsk = Pcmsk_copy
Return
Michael Schurr schrieb:> bei maximaler Zeiteffizienz.
Ich glaube nicht, daß jemand das als wirklichen Vorteil sieht, wenn beim
nicht Drücken die CPU-Last um 0,01% geringer ist, gegenüber der
Timermethode.
Auf jeden Fall ist es nicht merkbar.
Auch braucht fast jede Anwendung einen Timer, um zeitliche Abläufe (RTC,
Multiplex, Blinken usw.) zu realisieren.
Der Timerinterrupt läuft also eh immer und kann nicht gestoppt werden.
Effizienz ist nicht das Maximum eines Parameters, sondern das Optimum
aller Parameter.
Moin moin...
Peter Dannegger schrieb:> Ich glaube nicht, daß jemand das als wirklichen Vorteil sieht, wenn beim> nicht Drücken die CPU-Last um 0,01% geringer ist, gegenüber der> Timermethode.
Es geht doch hier ja gar nicht um den Kontrast zur Timermethode, sondern
um die Gegenüberstellung der Int_getriggerten Eventmethode einerseits,
zur stichprobenartig arbeitenden Pollingmethode andererseits. Letztere
muss auch im eventlosen Zustand ständige Abfragen und
Vergleichsoperationen ausführen, um überhaupt weiteren Handlungbedarf zu
erkennen. Ausserdem kann das zyklische Polling generell, wie z.B. auch
die Audiodigitalisierung, nur solche Dynamiken sicher detektieren, die
unterhalb der halben Pollingfrequenz liegen.
Eine Routine, die zufällig x-mal denselben Pegel detektieren und als
"statisch" erklären kann, während das Signal ausserhalb der Stichproben
quasi Narrenfreiheit besitzt, ist ja nicht als mathematisch/logisch
eindeutige Methode und damit als verlässlich zu bezeichnen. Aber genau
das will man doch bei jeder Art der sauberen Programmierung erreichen,
daß das Prozedurverhalten eindeutige und vor allem reproduzierbare(...)
Ergebnisse generiert.
Das ist auch im Hinblick auf Wartbarkeit und Verwendbarkeit als Modul,
ein starkes Argument. Ich sehe Zuverlässigkeit und Reproduzierbarkeit
eines detektierten Zustandes, als eines der prioritären Prinzipien an
und damit auch als Code-Effizienz im übergeordneten Sinne.
Vor allem kann Code der reproduzierbar verlässlichen Output liefert, auf
andere Einsatzgebiete portiert werden, gerade wenn es dort auch auf
kompromisslose Zuverlässigkeit ankommt.
Der wirklich effizienzgewinnende Teil der letzten Änderung, ist ja die
Begrenzung des Pchg_int auf das erste Ereignis. Das bewirkt, daß z.B.
auch stark prellende Kontakte nur einen einzigen Int samt
push/pop-Overhead pro Timerzyklus erzeugen. Die 'ruhigen', stabilen
Eingangskonstellationen verbrauchen, wie gehabt, nach dem zweiten
Timerzyklus ohnehin gar keine Prozesszeit mehr.
Ob nun der Timerinterrupt mit seinen 0,01% dazu auch noch wegfällt oder
nicht, habe ich ja auch nur als Option in Klammern dargestellt, die man
noch reinnehmen kann um damit eine 'puristisch reine', eventgetriggerte
Prozedur zu erreichen, die ohne akuten Event garnicht mehr in
Erscheinung tritt.
Michael Schurr schrieb:> Eine Routine, die zufällig x-mal denselben Pegel detektieren und als> "statisch" erklären kann, während das Signal ausserhalb der Stichproben> quasi Narrenfreiheit besitzt, ist ja nicht als mathematisch/logisch> eindeutige Methode und damit als verlässlich zu bezeichnen.
Doch kann man denn das hängt ausschließlich von den Rahmenbedingungen
ab. Indirekt ewähntest du schon das Nyquist Theorem das exakt diese
Grenze mathematisch formuliert. Alle externen Eregnisse die unterhalb
dieser Grenze ablaufen können auch mit einem Sampling das oberhalb
dieser Grenze liegt eindeutig sauber erfasst werden. Die Notwendigkeit
für ein Ereignisbasiertes System entfällt bzw. es stellen sich die
gleichen Verhältnisse dazu bei einem Sampling ein.
So bleibt also nur das Argument des Aufwandes, des Resourcenverbrauches.
Und da sieht es eben so aus das für Tasterabfragen wirklich nur eine
Verbesserung von Subprozentpunkten den Unterschied machen.
Michael Schurr schrieb:> Der wirklich effizienzgewinnende Teil der letzten Änderung, ist ja die> Begrenzung des Pchg_int auf das erste Ereignis. Das bewirkt, daß z.B.> auch stark prellende Kontakte nur einen einzigen Int samt> push/pop-Overhead pro Timerzyklus erzeugen. Die 'ruhigen', stabilen> Eingangskonstellationen verbrauchen, wie gehabt, nach dem zweiten> Timerzyklus ohnehin gar keine Prozesszeit mehr.
Exkat dieser Teil deiner Argumentation kann man auch als negativ
bewerten. Wir wissen das ein gültiges Tasterereignis im Frequenzbereich
< 100Hz liegt. Wir wissen auch das Störungen teilweise im
Frequenzbereich weit oberhalb von x kHz liegen können. Zudem wissen wir
das der PinChange mit Clock_CPU/4 maximaler Frequenz arbeiten kann. Das
hochfrequente Prellen des Tasters wird also dazu führen das
überproportional viele Resourcen in der PinChange ISR verschwendet
werden die keinerlei zielführende Resultate bringen werden. Benutzt man
einen Timer mit einer Frequenz von zB. 200Hz dann reduziert man also auf
Grund des Nyquist Theorems diese hochfrequenten Störungen und damit den
unnützen Verbrauch von Rechenzeit. Gleichzeitigt bleiben aber die
erreichbare Genauigkeit beider Verfahren erhalten, beide Verfahren sind
also zur Erreichung des Zieles identisch exakt.
Denoch gibt es Anwendungsfälle bei denen deine PinChange Methode
überlegen ist. Wenn man zb. einen Timestamp mit viel höherer Auflösung
als die 100Hz Auslöserate des Tasters diesem Event zuordnen muß. Dann
müsste man mit der Timer Methode diesen Timer mit wensentlich höherer
Frequenz laufen lassen. Und ab einem gewissen BreakEven Point wird die
PinChange Methode die Timer Polling/Sampling Methode outperformen.
Hagen Re schrieb:> Das> hochfrequente Prellen des Tasters wird also dazu führen das> überproportional viele Resourcen in der PinChange ISR verschwendet> werden
Nein, wird es nicht, wie sich aus meinem Text (und auch aus dem Code)
ersehen lässt.
Da du meine Texte und die Funktion des Codes offensichtlich nicht zur
Grundlage deiner Überlegungen nimmst, können wir auf weitere
Spekulationen dieser Art und unfundierte Behauptungen verzichten...
Wenn ich statt neue Wege und Tatsachen zu analysieren, lieber
Glaubensdinge und Dogmen erörtern möchte, gehe ich in einschlägige
Foren... ;-)
Um es nochmal anders zu betrachten:
Die Timer Methode impliziert einen digitalen Filter auf Grund des
Abtasttheorems (Nyquist). Diesen Filter hat man inklusive ohne
zusätzliche Resourcen.
Die PinChange Methode benötigt die Resource PinChange ISR und ebenso
einen Timer oder zus. softwarebasierte Filter um die gleiche
Effektivität zu erreichen.
Der Rsourcenverbrauch ist also höher da man nicht nur die CPU Zeit als
Resource betrachten darf sondern auch die benutzten Features der CPU.
Dazu kommt als Resource noch der Hirnschmalz den man investieren muß und
die erreichbare Stabilität aus Sicht des Zieles und der Vermeidung von
Störungen.
Im Falle einer einfachen Tasterabfrage meine ich das die Timermethode
die simpelste und gleichermaßen effektivste Methode ist, weil sie nach
folgenden Regeln arbeitet:
- keep it simple
- programmiere das Nötige mit dem minimalsten Aufwand
- benutzte aus zwei Methoden diejenige die die geringste Komplexität hat
Michael Schurr schrieb:> Wenn ich statt neue Wege und Tatsachen zu analysieren,
Glaubst du wirklich, einen neuen Ansatz gefunden zu haben, der die
Tastenabfrage jetzt revolutionär besser macht?
Das Thema Tastenabfrage, auf den ersten Blick logischerweise, über
Interrupts zu machen, taucht hier wöchentlich auf.
Einfach nur langweilig.
mfg.
Michael Schurr schrieb:> Nein, wird es nicht, wie sich aus meinem Text (und auch aus dem Code)> ersehen lässt.>> Da du meine Texte und die Funktion des Codes offensichtlich nicht zur> Grundlage deiner Überlegungen nimmst, können wir auf weitere> Spekulationen dieser Art und unfundierte Behauptungen verzichten...
Ich habe deine Argumentation sehr genau gelesen und möchte hier auf
deinen Hinweis auch eingehen.
Wenn das Prellen so schnell ist das es die Ausführungszeit der PinChange
ISR überholt, also die Hardware Grenze von CPU_Clock/4 überschreitet
(was immerhin auf AVRs ca. 2Mhz sind) dann filtert quasi die Hardware
für dich. Wenn das Prellen langsammer ist aber immer noch schneller als
die Ausführungszeiten deiner PinChange ISR dann führt dies dazu das
sofort nach Abarbeitung dieser ISR diese ISR wiederum aufgerufen wird.
Denn das Interruptflag wird erneut gesetzt. Angenommen deine PinChange
ISR kann nur mit maximal 100KHz arbeiten und der Taster prellt für 10ms
mit 500kHz, dann würde deine PinChange ISR die komplette CPU Zeit für
diese 10ms verbrauchen. Das kann mit einer Timer ISR nicht passieren da
diese eben nur mit 5ms Interval arbeitet.
Und dieses Verhalten wird durch den Entwickler provoziert ohne jeglichen
Gewinn, denn das Ziel lautete: ein Taster der max. mit 100Hz betätigt
werden kann soll so ausgelesen werden das man keine der 100Hz
Betätigungen vermisst. Und da besagt das Nyquist Theorem ganz klar:
lasse den Timer mit 200Hz laufen um dieses Ziel mathmeatisch beweisbar
erreichen zu können.
Das Problem mit der PinChange ISR ist es also das sie gerade auf jedes
Ereignis des Tasters sofort reagiert obwohl dies kontraproduktiv sein
muß.
Wir wissen das mit 100Hz ein Tasterevent kommt und davor aber x'male
mit >> 100Hz ein Prellen. Wir sind am Tasterevent interessiert und nicht
am Prellen. Wir möchten die Resourcen schonen und nur auf das reagieren
was relevant ist. Die PinChange Methode kann also nicht das leisten was
die Timer Methode in diesem Fall leistet.
Timer Methode benötigt einen langsammen Timer der oft sowieso schon
benutzt wird. PinChange benötigt den PinChange und entweder einen Timer
zusätzlich oder eine aufwnedigere Softwarefilterung. Beide leisten am
Ende das gleiche. Der Verbrauch an vorhandenen Resourcen ist also bei
der PinChange Methode höher. Gleiches gilt für die Komplexität der
Verfahren.
Michael Schurr schrieb:> Da du meine Texte und die Funktion des Codes offensichtlich nicht zur> Grundlage deiner Überlegungen nimmst
Vielleicht ging es ihm nur so wie mir, ich verstehe nicht, wie Dein Code
entprellen soll. Er enthält ja auch keinerlei Kommentare.
Wie ich das verstehe, wird beim ersten Pin-Change Interrupt der
Pin-Zustand eingelesen und weitere Interrupts für diesen Pin gesperrt.
Und nach einer Wartezeit wird dann der gespeicherte Zustand übernommen
und Pin-Change wieder freigegeben. Der Pin kann zwischenzeitlich wieder
eine völlig anderen Zustand haben, es kann auch nur ne Störnadel gewesen
sein.
Das entspricht also in der Funktion dem Klassiker:
Externer Interrupt + Delay.
P.S.:
Den PinB im Pin-Change-Interrupt zweimal einzulesen, heißt nicht, daß
diese Werte auch identisch sind. Externe Ereignisse sind asynchron.
Da sollte man also eine Zwischenvariable benutzen.
Peter Dannegger schrieb:> Michael Schurr schrieb:>> Da du meine Texte und die Funktion des Codes offensichtlich nicht zur>> Grundlage deiner Überlegungen nimmst>> Vielleicht ging es ihm nur so wie mir, ich verstehe nicht, wie Dein Code> entprellen soll. Er enthält ja auch keinerlei Kommentare.
Nein so ging es mir eigentlich nicht. Ich braucht nicht seinen Code zu
verstehen um zu meinen Schlußfolgerungen zu kommen.
Es gibt mehrere Wege:
1. er benutzt nur den PinChange:
Vorteil: nur eine Resource benutzt, identisch zur Timer Methode.
Nachteil: bekommt dann Probleme mit dem Prellen und muß per Sofwtare
aufwendig filtern.
2. er benutzt den PinChange als Intialzünder, deaktiviert diese ISR und
benutzt dazu einen Timer:
Vorteil: statt nun mit 200Hz Abtastrate arbeiten zu müssen wie bei der
Timer Methode hat er diese Abtastfrequenz auf 100Hz reduziert. Die
Timermethode muß also minimal doppelt so häufig nachschauen wie seine
Methode. Da aber Software für seine PinChange ISR + Timer ISR
programmiert werden muß verbraucht er doppelt soviele Resourcen in
diesem Bereich.
Nachteil: er benutzt 2 Hardware Resourcen statt eine wie bei der Timer
Methode.
Egal wie man es also dreht und wendet: die PinChange Methode ist
ineffektiver, sowohl beim Resourcenverbrauch wie auch bei der
Komplexität, wenn man die selbe Zielsetzung annimmt.
Ich sehe da nur einen Denkfehler: das Unverständis zum Abtasttheorem.
Peter Dannegger schrieb:> P.S.:> Den PinB im Pin-Change-Interrupt zweimal einzulesen, heißt nicht, daß> diese Werte auch identisch sind. Externe Ereignisse sind asynchron.> Da sollte man also eine Zwischenvariable benutzen.
Und das sind dann die versteckten Probleme die die Sache eben komplexer
machen im Vergleich zur simplen Sampling Methode nach Nyquist = Timer
Methode.
Wenn es um die Probleme deim Abtasten von anaolgen Werten per ADC geht
(Nyquist) ist das Verständnis der Entwickler vorhanden. Die Frage die
sich nun stellt ist warum manche Entwickler dieses Wissen nicht anwenden
können auf andere Probleme. Und eine Tasterabfrage ist so ein Problem.
Oder ist es wirklich sinnvoll einen analogen Wert am ADC so abzutasten
das wenn sich dieser Wert ändert sofort eine ansynchrone Abarbeitung per
"ADC_Change-ISR" anzustoßen und das dann auf den Zeitbereich per
zusätzlichen Filterungen (Timer, Delays etc.pp) wieder zu linearisieren
?
Thomas Eckmann schrieb:> Glaubst du wirklich, einen neuen Ansatz gefunden zu haben, der die> Tastenabfrage jetzt revolutionär besser macht?> Das Thema Tastenabfrage, auf den ersten Blick logischerweise, über> Interrupts zu machen, taucht hier wöchentlich auf.> Einfach nur langweilig.
...tsts... auf Beiträge die mich langweilen gehe ich in der Regel erst
gar nicht ein... von daher: Danke, für die Mühe... ;-)
Ich habe das Thema "Tastenabfrage mit Interrupts" eben nicht nur mit dem
ersten Blick euphorisiert, sondern seine Nachteile, die auftreten wenn
man den Pchg-Int unreflektiert benutzt, gesehen und dann ausgeschaltet.
Daß es mich "revolutionär" dünkt, hast du stichelig ins Feld geworfen...
wirst wohl emotionalen Grund dazu haben...
'***************
@ Hagen...
Alles Argumente, die nicht wirklich greifen im vorliegenden Fall.
Während das Polling ständig am werkeln ist, wacht meine Routine nur bei
einem realen PChg-Event auf und benötigt genau max. 1 PChg-Int pro
Zeitfenster und instabilem Eingang. Und die Pchg-Routine ist nun
wirklich minimalistisch und präzise zugleich.
Ich brauche keine 100Hz Abtastfrequenz, welche die ganze Zeit pollt,
testet und prüft... ich brauche den 100Hz Takt Pchg-getriggert genau 2
mal um einen Change abzuarbeiten, danach ist Ruhe. Auch dann, wenn der
unruhige Pin innerhalb dieser Periode noch x-mal weiterbounct!
Es scheint hier mehr um das Dogma:
"Entprellung und Interrupt ist Resourcenverschwendung und generell
tabu..!!"
zu gehen, ohne sich damit zu befassen, dass es mit der richtigen
Implementierung nur Vorteile bringt. Und zwar in sachen Präzision, wie
auch Timing. Nur verstehn muss halt, was hier gemacht wurde und wie der
Code arbeitet. Sonst bleiben die meisten 'Kritiken' einfach nur
Unkenrufe.
Auch Peter D.s Image als Board-Koryphäe und seine unbestritten enormen
Fach-Fähigkeiten, werden durch eine Alternativlösung keineswegs in Frage
gestellt. Aber es bedeutet auch nicht zwingend, dass von solcher Seite
deswegen stets nur die ultimativen Non-plus-Ultra-Lösungen kommen, die
als unantastbar, unverbesserbar, oder gar alternativlos zu respektieren
sind. Hier scheint es mir diesbezüglich viele "eifrige Jünger" zu geben,
die meinen, ihren Guru beschützen zu müssen, statt unvoreingenommen und
offen fü anderes zu sein.
Stichhaltige Gegenargumente, die das codetechnische Verhalten obiger
Routine richtig erfassen, habe ich hier jedenfalls noch keine gesehen.
Von den Bugs im Anfangsstadium und der diesbezüglich berechtigten,
konstruktiven Kritik mal abgesehen.
Nein, ich halte mich weder für einen Revoluzzer, noch für einen
Entdecker einer "grossen" Sache. Einen gewissen Perfektionismus mit
einfachen Mitteln zu Realisieren, macht mir einfach Spass... wenn's dann
endlich funzt. Das bedeutet für mich dann Effizienz.
Mike
Michael Schurr schrieb:> @ Hagen...>> Alles Argumente, die nicht wirklich greifen im vorliegenden Fall.
Ok dann liefere ich dir eines:
Implementiere deine Methode mit 4 Tastern + 4 andere Signalleitung die
den PinChange zwingend benötigen.
1. du wirst Probleme bekommen einen AVR so mit PinChange zu
programmieren das du innerhalb der PinChange ISR, die ja für den ganzen
Port gilt, zu erkennen welcher Pin nun einen PinChange ausgelösst hat.
2. du wirst Probleme bekommen bei 4 Tastern das nachfolgende Timer
Timing einzuhalten, der Aufwand steigt proportional da du ja nun für
jedes Event einen eigenen Timerwert pflegen musst. Du hast dann zwei
Möglichkeiten: defakto 4 Timer zu benutzten oder einen Timer mit festem
aber nun viel höherem Interval als 100Hz um 4 Zähler für die Events
programmieren zu können. Gerade letzteres führt zur Frage: warum dann
nicht gleich mit nur einem Timer sampeln ? der dann sogar wieder
langsammer laufen kann = 200Hz.
Bei der Timer Methode tastet man alle 4 Taster im gleichen Interval ab,
also synchron zueinander innerhalb einer einzigen Routine und sogar
Variablen.
Ich habe da so eine Design-Regel in meiner Arbeit als Entwickler: wenn
eine gewählte Methode ohne Probleme höherwertige Probleme genauso gut
erschlagen kann dann ist diese Methode besser als eine andere Methode
die dann erst richtig Probleme verursacht. Und ausgehend von einem
Taster auf zB. 4 Taster ist es eben so das die Timer Sampling Methode
enorm einfach anzupassen ist und mit gleicher Effektivität nun ein
komplexeres Problem lösen kann.
Über das Abtasttheorem und dessen Konsequenzen müssen wir ja nicht mehr
diskutieren. Wir wissen ja das die Sampling Methode nur doppelt so oft
aufgerufen werden muß wie das zu erwartende Ereignis auftreten kann.
Wenn dieses Theorem nicht verletzt wurde dann unterscheiden sich beide
Methoden von der Zielsetzung nicht mehr. Dh. die Exaktheit und
Genauigkeit ist die gleiche bei beiden Verfahren. Du musst also uns
beweisen das deine Methode einen entscheidenden Vorteil gegenüber der
Timer Methode hat. Und da sehe ich eben keine logisch vernünftigen
Argumente deinerseits.
Ich entwickele mein Wissen also nicht nur ausgehend von einem konkreten
gegenwätigen Problem sondern immer in Hinblick darauf das sich ähnliche
Probleme auch in Zukunft stellen werden. Somit verfolge ich immer auch
das Ziel eine Problemlösung wiederverwenden zu können.
Mike, ich diskutiere hier mit dir nur aus einem Grund heraus: nicht weil
ich deine Sichtweise diskreditieren möchte noch deine Ideen herabsetzen
möchte, sondern um dir meine Sichtweise und die logischen Gründe dafür
näher zu bringen. Letzendlich sehe ich in deinen Argumenten exakt die
Denkfehler die ich damals als Anfänger gemacht habe.
PS: ich rede hier immer von Effektivität und nicht Effizienz und das aus
gutem Grund. Denn es geht hier nicht nur um die Betrachtung welche
Resourcen wir im AVR haben und verbrauchen sondern auch um den Effekt
den die eigenen Entwicklungsarbeit für uns hat. Und da meine ich eben
das die Sampling Methode per Timer die höhere Effektivität hat.
Michael Schurr schrieb:> Stichhaltige Gegenargumente, die das codetechnische Verhalten obiger> Routine richtig erfassen, habe ich hier jedenfalls noch keine gesehen.> Von den Bugs im Anfangsstadium und der diesbezüglich berechtigten,> konstruktiven Kritik mal abgesehen.
Ich habe keine, wie du so schön schreibst, stichhaltigen Gegenargumente
zu deinem Sourcecode. Es gibt auch keine da du sauber entwickelt hast.
Man kann es so machen.
Mein Gegenargument ist das du am Thema der Zielstzung vorbei entwickelt
hast und es einfacher geht bei gleicher Exaktheit der Resultate und
annähernd vergleichbarer CPU Auslastung. Die anderen Resourcen die deine
Methode benötigt disqualifiziert sie aber zur Sampling Methode. Die
Einsetzbarkeit auf nur ein spezielles Problem im Vergleich zur
Erweiterbarkeit der Sampling Methode disqualifiziert sie ebenfalls.
Ich weiß das du das anders siehst ;)
Wie man es macht, hängt doch davon ab, wieviele Taster/Schalter zu
verarbeiten sind und wie schnell reagiert werden muß.
Bei einer Tastenmatrix reichen zum einen die Eingänge des Controllers
nicht aus, und zum anderen ist für die Dekodierung sowieso einige Zeit
nötig, während der aber keine Interrupts blockiert werden müssen. Da
gibt es keine Alternative zur zyklischen Abfrage in einer Timer-ISR.
Hier ist PCINT auf verlorenem Posten.
PCINT bietet sich bei einem oder nur wenigen Tastern an, oder wenn auf
Impulse von z. B. Reedrelais' schnell reagiert werden soll. Dabei ist
eine Filterung mit ext. RC-Glied einem 'Software-Filter' vorzuziehen, da
der integrierte Impuls nicht mehr zwischen GND und VCC wackelt, sondern
um ein Maß, was deutlich unter der Hysterese eines Eingangs (beim AVR)
liegt.
Eine RC-Filterung schützt den Eingang zudem vor zu schneller
Interruptfolge und in gewissen Rahmen auch vor ext. Überspannung, wenn
der Taster räumlich entfernt angeordnet ist.
Anfang der Woche hatte ich dazu etwas in der Codesammlung geschrieben
und auch den Kurvenverlauf für einen typischen Eingabetaster (Digitast)
gezeigt.
"EIN-AUS mit Taster per Interrupt"
hm gerade auch bei Reedrelais würde ich eher das Sampling benutzen. Es
gillt in jedem fall das das Prellen höherfrequenter ist als das
eigentliche Eregnis. Ergo muß man nur die Samplingfrequenz korrekt
anpassen und filtert so ohne externen Aufwand und ohne weiteren internen
Aufwand automatisch.
Nur wenn wir einen Timestamp dem Event zuordnen müssen der selber eine
viel größere Auflösung hat als die Auslösegeschwindigkeit des Ereignises
muß man ereignisbasiert arbeiten.
Nur wenn wie in Echtzeit, auch eine Definitionssache, darauf reagieren
müssen lohnt sich ereignisbasiert zu arbeiten.
Nur wenn die Synchronität bei der Auswertung mehrer Ereignisse
kontraproduktiv wird, also die Asynchronität zwischen den Ereignissen
für uns wichtig ist, müssen wir ereignisbasiert arbeiten.
Und wenn wir mal konsequent zu Ende denken dann gilt: wir arbeiten in
einer CPU immer nach dem Sampling Verfahren denn auch die CPU arbeitet
nur Taktbasiert, ergo beträgt die maximale Samplingfrequenz aller
Ereignisse auf die die CPU reagieren kann auch nur die der Taktfrequenz
der CPU.
Hagen Re schrieb:> 1. du wirst Probleme bekommen einen AVR so mit PinChange zu> programmieren das du innerhalb der PinChange ISR, die ja für den ganzen> Port gilt, zu erkennen welcher Pin nun einen PinChange ausgelösst hat.
Nein, werde ich nicht, weil genau diese differenzierte Erkennung in der
PChg-Isr ohnehin gemacht wird und zudem nur jene Eingange als Auslöser
in Frage kommen, die im PMSK aktiviert sind..
Ich brauch nur das Changed_Pins Byte auswerten... das enthält genau
jenen Eingang als eine "1", der den Int getriggert hat. Alle andern sind
Zero.
Hagen Re schrieb:> 2. du wirst Probleme bekommen bei 4 Tastern das nachfolgende Timer> Timing einzuhalten, der Aufwand steigt proportional da du ja nun für> jedes Event einen eigenen Timerwert pflegen musst.
Auch das ist grottenfalsch... :-)
In der PChg_Isr werden alle (per PCMSK aktivierten) Bits in der Breite
des gesamten Ports per Ver-ODER-ung gesammelt und dann mit dem Timer_Int
als Bytewert in einem Rutsch und mit Hilfe von Bitmanipulationen,
gemeinsam ausgewertet und prozessiert. Nix "4 Timerwerte pflegen" und
son Zeug...!
Alle Change-Events parallel 'sammeln', byteweise verarbeiten, das
Ausgangsbyte mit den "ruhigen" Bits updaten und jene Bits die sich
verändert haben, beobachten, bis sie innerhalb einer Timerperiode
unverändert waren... dann auch diese im Ausgangsbyte updaten... fertig.
Hagen Re schrieb:> nicht weil> ich deine Sichtweise diskreditieren möchte noch deine Ideen herabsetzen> möchte, sondern um dir meine Sichtweise und die logischen Gründe dafür> näher zu bringen.
Sorry, aber sowohl deine Sichtweise, als auch deine "logischen Gründe"
sind in Bezug auf meine Routine total unlogisch und unzutreffend...
Wenn du nun bitte eine argumentative Denkpause anfügen könntest, anstatt
ohne wirkliche Kenntnis des Codeablaufen munter weiter ins Blaue zu
spekulieren, wäre ich dir sehr verbunden... ohne sich wirklich Mühe zu
machen etwas zu verstehen, geht es nämlich vom sachlichen Kritikanspruch
schnell in Richtung Diskreditierung. Und das steht dir ja ferne... ;-)
Mike
Michael Schurr schrieb:> In der PChg_Isr werden alle (per PCMSK aktivierten) Bits in der Breite> des gesamten Ports per Ver-ODER-ung gesammelt und dann mit dem Timer_Int> als Bytewert in einem Rutsch und mit Hilfe von Bitmanipulationen,> gemeinsam ausgewertet und prozessiert. Nix "4 Timerwerte pflegen" und> son Zeug...!>> Alle Change-Events parallel 'sammeln', byteweise verarbeiten, das> Ausgangsbyte mit den "ruhigen" Bits updaten und jene Bits die sich> verändert haben, beobachten, bis sie innerhalb einer Timerperiode> unverändert waren... dann auch diese im Ausgangsbyte updaten... fertig.
Na da haben wirs doch !
1. du wertest mit dem gleichen Timer Interval alle PinChange's aus. Das
Argument das du gezielt auf einen Taster umgehend reagieren kannst gilt
also nicht mehr da du nur noch in einem festen Interval auf mehrere
Changes reagieren kannst. Somit ist dies identisch zum Abtasten.
2. du kannst nicht innerhalb der PinChange ISR herausfinden welcher
maskierte Pin die ISR ausgelöst hat. Das geht nicht weil der AVR dafür
keine Hardware Unterstützung anbietet. Die einzige Möglichkeit ist es
den Pinzustand auszulesen und mit einem zwischengespeicherten zu
vergleichen. Dies muß in Relation zur nachfolgenden Timer Auswertung in
einer separaten Variablen erfolgen. Beim Sampling entfällt diese
Variable.
3. du verbrauchst zwei Resourcen: PinChange und Timer.
Der einzige Vorteil aus Sicht der CPU Zeit den ich sehe ist das deine
Methode nur dann aktiv wird wenn Taster gedrückt/losgelassen werden.
Dies ist unbestritten ein Vorteil aus Sicht der CPU Zeitauslastung wenn
man es in absoluten Zahlen fast. Aber, lohnt sich diese Komplexität,
dieser Resourcenverbrauch an 2 HW-Resourcen + FLASH Speicher für den
komplexeren Code in Relation zu den ca. 20 Opcodes die alle 200Hz in
einer Timer Routine beim Sampling benötigt werden ? Ich denke nicht.
Alle anderen propagierten Vorteile: wie Exaktheit, Komplexität usw. habe
ich oben schon widerlegt.
Hagen Re schrieb:> Ergo muß man nur die Samplingfrequenz korrekt> anpassen und filtert so ohne externen Aufwand und ohne weiteren internen> Aufwand automatisch.
Na da spendiere ich meiner Schaltung doch lieber 10k + 10nF als Filter,
als mit 1-10kHz Dauerlauf auf Verdacht abzutasten.
Je kleiner das Reedrelais, umso schneller kann es schalten.
Michael Schurr schrieb:> beobachten, bis sie innerhalb einer Timerperiode> unverändert waren...
Ooops...das ist natürlich selbstgemachter Humbug... die Changed_Pins
brauchen natürlich nicht "beobachtet" zu werden, sondern werden
automatisch upgedatet, sobald sie eine Timerperiode lang stabil waren...
Michael Schurr schrieb:> sobald sie eine Timerperiode lang stabil waren...
Dies ist die entscheidende Passage: das Abtasttheorem besagt exakt das
Gleiche wenn man mit doppelter Frequenz zur Eventfrequenz abtastet.
Du machst also im Extremfall folgendes:
Alle 100Hz kommt ein PinChange und mit einem 200Hz Timer tastest du
nochmal ein zweites mal ab.
Die Sampling Mehtode macht folgendes:
Alle 200Hz taste ab und vergleiche mit dem vorherigen Zustand = 100Hz.
In beiden Fällen kommt exakt das Gleiche heraus.
Nur wenn der Taster nicht mehr alle 100Hz gedrückt wird ändert sich
zugunsten deiner Methode der Verauch an CPU Zeit.
Wird der Taster schneller als 100Hz gedrückt machen beide Methoden einen
Fehler.
Stellt sich nun die Frage: welche Mehtode ist insgesamt effektiver ?
Die Timer Methode:
- simpel
- ausbaufähig
- weniger HW-Resourcen
- geringere Komplexität
- dadurch weniger fehlerträchtig
Die PCINT Methode:
- weniger Rechenleistung wenn sich nichts am Taster verändert
Alle 200Hz werden 20 OpCodes beim Sampling benötigt. Bei 8MHz Takt sind
dies 0,05% der Rechenleistung.
Das wars mit den Vorteilen.
Mike, du musst es doch mal so betrachten. Dein Ziel hier deine Methode
vorzustellen, und damit der Nutzwert für die Leute die ihn anwenden
wollen, besteht doch darin sie in ein weiterführendes Projekt
einzubauen. Damit muß letzendlich die Betrachtungsweise der Effizienz zu
einer Betrachtungsweise der Effektivität werden. Denn nur deinen
Sourcecode als einzigem Bestandteil eines Programmes zu betrachten ist
widersinnig. Denn erstens erledigt sich dann das Thema Effizenz da man
ausreichend Resourcen zur Verfügung hat. Zweitens ist eine solche
Effizienzbewertung im Vergleich zu anderen Methoden hinfällig. Ergo:
stellt sich die Frage mit welchen Minimal-Mitteln kann das Ziel erreicht
werden da man ja annehmen muß das die Resourcen in einer größeren
Anwendung immer knapper werden, oder eben bestimmte Resourcen eh schon
vorhanden und benutzt werden (wie eben ein Timer). Gleichermaßen muß man
dann hinterfragen welche Seiteneffekte wird es haben wenn ich bestimmt
Resourcen blockiere für die spätere Anwendung.
So jedenfalls ist meine Sicht auf diesen Thread und daraus resultiert
auch meine Wertung.
Gruß Hagen
Hagen Re schrieb:> Wird der Taster schneller als 100Hz gedrückt machen beide Methoden einen> Fehler.
Das muß nicht so sein. Durch schnelles Anschlagen eines Tasters wird ein
kurzer Impuls erzeugt, der per PCINT schnell und zuverlässig erkannt
wird: siehe Bild.
Nach ca. 2ms ist der Kontakt erkannt und nach ca. 4ms wieder auf
Ruhepegel. Soll sich jeder selber sein Urteil bilden.
Hagen Re schrieb:> Du machst also im Extremfall folgendes:> Alle 100Hz kommt ein PinChange und mit einem 200Hz Timer tastest du> nochmal ein zweites mal ab.
Hallo "Mr. Abtasttheorem", ...selten sowas von lernresistent und daneben
bei einer "Analyse" gelesen.. Daß der PChg_int nur auslöst, wenn auch
ein solcher Event auftritt, ist dir aber schon klar? Daß er nur 1mal
gebraucht wird und daher der entsprechende Eingangspin für den Rest des
laufenden Timerintervalls aus dem PChg ausmaskiert wird, ist dir auch
klar?
Nein, sicher nicht... war nur rhetorisch.
Da kommt eben nicht dasselbe raus, schon alleine dewegen, weil der
PChg-Int jeden(!) kurzen Flankenwechsel erfasst, während das Pollen nur
zufällig im Nebel stochert, um einen Pegelwert zu erfassen. Wenn da
wenige µs voerher oder nachher ein Flankenwechsel war, merkt die
Pollingroutine nix davon und gibt stattdessen ein falsches "stabil"
Argument weiter.
Dein (uni??)theoretischer Firlefanz liefert nur dann korrekte Schlüsse,
wenn er richtig eingesetzt wird... und das wird er von dir ganz
offensichtlich nicht!
Hagen Re schrieb:> Nur wenn der Taster nicht mehr alle 100Hz gedrückt wird ändert sich> zugunsten deiner Methode der Verauch an CPU Zeit.
Ah ja... du meinst wohl, nur wenn man Taster langsamer als mit 100Hz
betätigt, hat meine Methode Vorteile... oh DAS ist aber ein gaaanz
schlimmes Manko...!!! Wo doch jeder Old Dadderhand locker mit 150Hz auf
den Tasten was reinhackt. Haha, klasse!
Im Übrigen ist 100Hz eine Frequenzangabe und keine Zeitangabe. Man kann
einen Taster evtl. mit Hz bezittern, oder man kann kann alle 10ms einen
Taster drücken. Aber nicht alle 100Hz einen Taster drücken...
Und zu deinem letzten Post:
Da wird garnix blockiert an Resourcen. Die schon vorhandene Auswertung,
welche Taste den Interrupt generiert hat, ist sogar nützlich für andere
Rotinen, die diese Info ebenfalls benötigen! Das Argument
"Resourcenblockierung" ist auch nur Hot_Air!
Bist du jetzt eigentlich bald fertig mit deiner nichtdiskreditierenden
Diskreditierungsorgie...? Das hat ja schon was Fanatisches an sich, Dein
missionarischer Eifer des Madigmachens... ;-)
******
Hagen Re schrieb:> Denn erstens erledigt sich dann das Thema Effizenz da man> ausreichend Resourcen zur Verfügung hat.
Ach, und wozu überhaupt noch was Effizientes proggen, wenn es doch
Resourcen im Überfluss gibt...?
Hagen Re schrieb:> Gleichermaßen muß man> dann hinterfragen welche Seiteneffekte wird es haben wenn ich bestimmt> Resourcen blockiere für die spätere Anwendung.
Hauptsache gekontert, auch wenn er sich selbst diametral widerspricht in
einem einzigen Absatz...
...schizo..? Oder merkst du einfach nix mehr, auf deinem
Mießmuscheltrip?
Ich wünsche dir gute Besserung... dieser, wenigstens psychologisch
interessante, Disput bringt mir keine neuen Erkenntnisse mehr, ausser
daß ich da subjektiv eine subtile Art von Neid bei dir und deinen
endlosen, hohlen Kontra-Argumenten erspüre.
Mach doch mal was Kreatives, statt hier so verbissen erfolglos den
Marcel Reich-Ranicki der µC-Progger zu imitieren... :-))
Ich jedenfalls geh jetzt raus an die Sonne...
Michael Schurr schrieb:> Ich jedenfalls geh jetzt raus an die Sonne...
Na endlich mal was Vernünftiges.
Da kannst du dann über Vorwiderstände ohne Leuchtdioden nachdenken. Auch
so ein beliebtes Vollpfostenthema, daß niemanden wirklich interessiert.
mfg.
M. N. schrieb:> Hagen Re schrieb:>> Wird der Taster schneller als 100Hz gedrückt machen beide Methoden einen>> Fehler.>> Das muß nicht so sein. Durch schnelles Anschlagen eines Tasters wird ein> kurzer Impuls erzeugt, der per PCINT schnell und zuverlässig erkannt> wird: siehe Bild.> Nach ca. 2ms ist der Kontakt erkannt und nach ca. 4ms wieder auf> Ruhepegel. Soll sich jeder selber sein Urteil bilden.
Und was bringt das ? So hast du nämlich einen Störimpuls zuverlässig
detektiert und nicht das Betätigen wie gewünscht zuverlässig erkannt.
Also kommt der Timer nach dem PCINT ins Spiel der dann 50ms später
erneut den Taster abfragt und nur wenn dann der Taster immer noch
betätigt ist wird ein Tasterevent erzeugt. In deinem Falle also kein
Tasterereignis aber ein unnötiger PCINT.
Michael Schurr schrieb:> Hallo "Mr. Abtasttheorem", ...selten sowas von lernresistent und daneben> bei einer "Analyse" gelesen.. Daß der PChg_int nur auslöst, wenn auch> ein solcher Event auftritt, ist dir aber schon klar? Daß er nur 1mal> gebraucht wird und daher der entsprechende Eingangspin für den Rest des> laufenden Timerintervalls aus dem PChg ausmaskiert wird, ist dir auch> klar?> Nein, sicher nicht... war nur rhetorisch.
Doch das ist mir klar und habe ich auch so schon in den vorherigen
Positing analysiert für dich.
Egal, letztendlich habe ich nur noch eine Bemerkung zu machen: ist dir
mal aufgefallen welche Rethorik du an den Tag legst ?
Hagen Re schrieb:> Und was bringt das ? So hast du nämlich einen Störimpuls zuverlässig> detektiert und nicht das Betätigen wie gewünscht zuverlässig erkannt.>> Also kommt der Timer nach dem PCINT ins Spiel der dann 50ms später> erneut den Taster abfragt und nur wenn dann der Taster immer noch> betätigt ist wird ein Tasterevent erzeugt. In deinem Falle also kein> Tasterereignis aber ein unnötiger PCINT.
Das ist kein Störimpuls und einen Timer verwende ich auch nicht. Bei
genauer Lektüre hätte es Dir klar sein sollen.
Aber was soll ich hier gegen Windmühlen antreten?
M. N. schrieb:> Hagen Re schrieb:>> Und was bringt das ? So hast du nämlich einen Störimpuls zuverlässig>> detektiert und nicht das Betätigen wie gewünscht zuverlässig erkannt.>>>> Also kommt der Timer nach dem PCINT ins Spiel der dann 50ms später>> erneut den Taster abfragt und nur wenn dann der Taster immer noch>> betätigt ist wird ein Tasterevent erzeugt. In deinem Falle also kein>> Tasterereignis aber ein unnötiger PCINT.>> Das ist kein Störimpuls und einen Timer verwende ich auch nicht. Bei> genauer Lektüre hätte es Dir klar sein sollen.> Aber was soll ich hier gegen Windmühlen antreten?
Mit anderen Worten möchtest du einen 2ms langen Tastendruck detektieren
?
Nachfolgend deine Lektüre:
>Hagen Re schrieb:>> Wird der Taster schneller als 100Hz gedrückt machen beide Methoden einen>> Fehler.>Das muß nicht so sein. Durch schnelles Anschlagen eines Tasters wird ein>kurzer Impuls erzeugt, der per PCINT schnell und zuverlässig erkannt>wird: siehe Bild.>Nach ca. 2ms ist der Kontakt erkannt und nach ca. 4ms wieder auf>Ruhepegel. Soll sich jeder selber sein Urteil bilden.
Ich bezog mich darauf das der Taster minimal 10ms gedrückt sein muß, und
alles was drunter ist ist ein Störimpuls. Vielleicht wird dir jetzt
meine Aussage klarer.
Peter Dannegger schrieb:> Vielleicht ging es ihm nur so wie mir, ich verstehe nicht, wie Dein Code> entprellen soll. Er enthält ja auch keinerlei Kommentare.>> Wie ich das verstehe, wird beim ersten Pin-Change Interrupt der> Pin-Zustand eingelesen und weitere Interrupts für diesen Pin gesperrt.>> Und nach einer Wartezeit wird dann der gespeicherte Zustand übernommen> und Pin-Change wieder freigegeben. Der Pin kann zwischenzeitlich wieder> eine völlig anderen Zustand haben, es kann auch nur ne Störnadel gewesen> sein.
Peter, Du hast recht.
In der Wd_isr muss natürlich stehen:
If Changed_pins_sum = 0 Then
Deb_pinb = PINB anstatt: Deb_pinb = Last_Pins_state
Else
.
.
Hab ich in der obigen Aktualisierung falsch übernommen und ist mir nicht
aufgefallen.
Das wirkt sich sonst genau in diesem besonderen Fall aus, wenn es ein
einzelner Spike bzw. ein Burst war, der den ersten Flankenwechsel im
Endeffekt wieder annuliert UND wenn gleichzeitig im darauffolgenden
Timerinterval kein aktualisierender PChg-Event auftritt.
Bei einem Changed_pin_sum = 0 im Timer-Int ist jedoch garantiert, daß es
innerhalb des gesamten vorangegangenen Timerzeitfensters, keinen
Change-Event am Eingangsport gegeben hat. Somit ist in diesem Fall das
gesamte PINB stabil und gültig und kann ins Ausgangsbyte kopiert
werden..
Brilliant beobachtet, danke !