Die beiden Zähler werden alle 20sec ausgewertet und auf 0 gesetzt.
Leider sind sie nicht voneinander unabhängig. Der zweite Zähler zeigt
die Hälfte der Impulse des ersten an obwohl er im Leerlauf ist.
Warum?
Danke für Unterstützung.
ich glaube das Problem gefunden zu haben:
der pullup geht auf plus. ausgelöst wird die isr bei fallender Flanke.
Deswegen muss PINC==0 ausgewertet werden.
Karl K. schrieb:> ich möchte die Impulse zweier Stromzähler ...
Wie sehen die Impulse an den Portpins aus (Abstand, Dauer, Form)?
Sind die Pulse sauber entprellt?
Entsprechen die Zählerstände (bis auf diesen Faktor 2) deinen
Erwartungen?
Karl K. schrieb:> Deswegen muss PINC==0 ausgewertet werden.
Eigentlich sollten die Pulse doch ein Anfang und ein Ende haben, so dass
es egal sein sollte, welche Flanken du zählst.
Rainer W. schrieb:> Eigentlich sollten die Pulse doch ein Anfang und ein Ende haben, so dass> es egal sein sollte, welche Flanken du zählst.
flanke Pin2 runter => isr wird ausgelöst:
Pin2 ==0, Pin3 ==1(pullup)
flanke Pin2 wieder rauf => isr wird ausgelöst:
Pin2 ==1, Pin3 ==1
geht ein pin auf 0 wird der andere doppelt gezählt weil er bei fallender
und steigender Flanke jeweils ==1 ist.
So funktioniert es korrekt:
Karl K. schrieb:> u8 storagePINC=PINC;
Dass diese Variable den Code kein bisschen besser lesbar macht, muss ich
nicht erklären, oder? Außerdem ignoriert sie völlig die Konfiguration
von
> #define elt_port C
Lass diese Makro-Spielereien lieber weg.
> So funktioniert es korrekt ...
?
Und wenn die beiden kurz hintereinander auslösen? Also z.B. pin400,
gleich darauf pin1000, während pin400 noch auf 0 liegt?
Steve van de Grens schrieb:> Karl K. schrieb:>> u8 storagePINC=PINC;>> Dass diese Variable den Code kein bisschen besser lesbar macht, muss ich> nicht erklären, oder? Außerdem ignoriert sie völlig die Konfiguration> von>>> #define elt_port C>> Lass diese Makro-Spielereien lieber weg.
Der zweite Zähler ist zusätzlich dazugekommen. Deswegen musste der Code
angepasst werden. Aber ich glaube du hast recht.
>> u8 storagePINC=PINC; sollte Fehler verhindern, wenn ein zweiter Impuls
innerhalb der isr ausgelöst wird. Aber was soll's - so ist es besser:
Nun gut, die Makros willst du beibehalten.
> u8 storagePINC=PINC sollte Fehler verhindern, wenn ein zweiter Impuls> innerhalb der isr ausgelöst wird
Dann mache es so:
Karl K. schrieb:> ich möchte die Impulse zweier Stromzähler über zwei Pins am gleichen> Port auswerten:
Es ist ganz sicher eine ganz beschissene Idee, das über
Pinchange-Interrupts zu machen. Die Hardware der ollen ATmega bietet
keine Möglichkeit dafür, das zuverlässig umzusetzen. Es gibt kein
Strobe-Register für Pegelwechsel einzelner Pins und nur ein
Interruptflag für den ganzen Port.
Es ist also völlig unmöglich, in einer Pinchange-ISR zuverlässig
festzustellen, welche Pins des Ports gewackelt haben.
Mit den Eingängen INT0 und INT1 (PD2, PD3) geht es vielleicht besser.
Allerdings scheinen die Signale langsam genug zu sein, dass die ISR auch
bei obigem Ansatz keine Impulse verpasst. Der Sperrmechanismus wird wohl
nötig sein, wie S.L. gerade sehr schön dargestellt hat.
Steve van de Grens schrieb:> Mit den Eingängen INT0 und INT1 (PD2, PD3) geht es vielleicht besser.
Das hilft natürlich. Man kann auch einen dieser beiden Pins über INTx
betreiben und einen zweiten über den PCINT3. Dann geht das über einen
Port, weil man über das Maskenregister dafür sorgen kann, dass der über
INTx betriebene Pin den PCINT3 eben nicht auslöst. Und Natürlich sollte
das dann auch keiner der sonstigen Pins des PortD tun.
Damit hat man dann die eindeutige Erkennbarkeit sichergestellt.
> Allerdings scheinen die Signale langsam genug zu sein, dass die ISR auch> bei obigem Ansatz keine Impulse verpasst.
Du verstehst nicht, dass diese Signale voneinander unabhängig sind und
deshalb rein zufällig auch mal gleichzeitig oder (viel gefährlicher)
nahezu gleichzeitig toggeln können. Und: BUMM.
> Der Sperrmechanismus wird wohl> nötig sein, wie S.L. gerade sehr schön dargestellt hat.
Das auf jeden Fall. Und zwar ordentlich, d.h.: für jeden Messkanal
extra.
Bei diesen ganzen Problemen ist aber das Konzept an sich in Frage zu
stellen!
Polling über eine Timer-IRQ löst praktisch alle Probleme viel
einfacher...
Ob S. schrieb:> Es ist ganz sicher eine ganz beschissene Idee, das über> Pinchange-Interrupts zu machen. Die Hardware der ollen ATmega bietet> keine Möglichkeit dafür, das zuverlässig umzusetzen. Es gibt kein> Strobe-Register für Pegelwechsel einzelner Pins und nur ein> Interruptflag für den ganzen Port.>> Es ist also völlig unmöglich, in einer Pinchange-ISR *zuverlässig*> festzustellen, welche Pins des Ports gewackelt haben.
ähm hust. Natürlich kann man in der Pin-Change-ISR Flanken auswerten.
Man muss nur selbst paar Zeilen Code schreiben.
Veit D. schrieb:> ähm hust. Natürlich kann man in der Pin-Change-ISR Flanken auswerten.> Man muss nur selbst paar Zeilen Code schreiben.
Pinchange reagiert überhaupt nur auf Flanken. Insofern ist dein Einwurf
schon mal von Hause aus mal völlig idiotisch.
Das Problem ist halt nur: man kann nicht sicher sein, an welchem Pin
diese Flanken erfolgt sind, weil es bei den ollen AtMega halt kein
Register gibt, was man dazu befragen könnte (bei neuzeitlichen hingegen
schon).
Kapierst du jetzt das Problem?
Veit D. schrieb:> Natürlich kann man in der Pin-Change-ISR Flanken auswerten.> Man muss nur selbst paar Zeilen Code schreiben.
Ein Beispiel für 4 Kanäle habe ich gerade zur Hand:
Mi N. schrieb:> Ein Beispiel für 4 Kanäle habe ich gerade zur Hand:
Typisches Produkt von Leuten, die wirklich Null Ahnung von der Hardware
haben, mit der sie da arbeiten.
Also: du versuchst da, über den Pegel, die eine ISR irgendwann mal
liest irgendwelche Rückschlüsse auf Flanken zu ziehen, die in der
Vergangenheit aufgetreten sind.
Das muss (und wird) oft scheitern. Man muss kein Genie sein, um das
erkennen zu können. Insbesondere natürlich dann, wenn die Flankenwechsel
von mehreren Eingänge in zeitlich Größenordnungen liegen, die mit dem
Interruptsystem auf Grund der Latenz und Laufzeit der ISRs nicht mehr
auflösbar sind.
Ob S. schrieb:> Das muss (und wird) oft scheitern. Man muss kein Genie sein, um das> erkennen zu können. Insbesondere natürlich dann, wenn die Flankenwechsel> von mehreren Eingänge in zeitlich Größenordnungen liegen, die mit dem> Interruptsystem auf Grund der Latenz und Laufzeit der ISRs nicht mehr> auflösbar sind.
Das gilt natürlich insbesondere für voneinander unabhängige
Eingangssignale. Die köennen nämlich zufällig jederzeit auftreten. Also
auch mal sehr kurz nacheinander.
Du kannst einfach nicht "in Hardware" denken. Sehr schlecht für
µC-Programmierer...
Ob S. schrieb:> Typisches Produkt von Leuten, die wirklich Null Ahnung von der Hardware> haben, mit der sie da arbeiten.
Bevor Du lästerst, solltest Du den Code vielleicht mal ansehen. Das XOR
erkennt die Änderung und das AND die Richtung der Flanke. Perfekt, so
mache ich das auch in meiner Entprellib.
Da die Signale recht langsam sein dürften, kann eine zusätzliche
Entprellung/Entstörung aber nicht schaden. Das Schalten eines
Leistungsverbrauchers in der Nähe könnte eine Pseudoflanke generieren.
So ein AVR ist ja recht fix (50ns Puls bei 20 MHz).
Ob S. schrieb:> Du kannst einfach nicht "in Hardware" denken. Sehr schlecht für> µC-Programmierer...
Mir scheint du hast die Aufgabe überhaupt nicht verstanden. Hast du dich
überhaupt schon mit dem zeitlichen Verlauf des Signals befasst um das es
hier geht? Es geht hier jedenfalls nicht um die Erfassung von
Nadelimpulsen.
Ob S. schrieb:> Kapierst du jetzt das Problem?
Ich verstehe, was du meinst. Hier können wir allerdings davon ausgehen,
dass die Impulse bereits entprellt sind und lange genug anhalten, um per
Software innerhalb der ISR vom I/O Pin abgefragt zu werden.
Vielen dank für das Beispiel - so ähnlich mache ich es.
was mich verwundert, ist die Änderung der Systematik.
PCINT10 ist das dritte Bit von PCMSK1. Es hat demzufolge den Wert 0 oder
1 nicht 4. Die 4 ergibt sich erst durch die Stellung im Byte. Der
Ausdruck (1<<PCINT10 | 1<<PCINT11 | 1<<PCINT12 | 1<<PCINT13) ergibt dann
immer entweder 2 oder 0.
Müsste es nicht richtig heißen
port_neu &= (PCMSK1);
????
Karl K. schrieb:> Müsste es nicht richtig heißen> port_neu &= (PCMSK1);
J...-Nein.
Hier wird mit einer Konstanten maskiert, die nur die aktiven Kanäle
zuläßt:
port_neu &= (1<<PCINT10 | 1<<PCINT11 | 1<<PCINT12 | 1<<PCINT13);
oder aufgelöst
port_neu &= 0x3c;
PCMSK1 ist ein Register im Controller, das auch noch weitere Bits
gesetzt haben könnte, die an anderen Stelle ausgewertet werden könnten.
Alles im weichgespülten Konjunktiv ;-)