Ich habe an meinem Arduino nano ein Interruptprogramm bei wechselnder Flanke am Pin 3.
Nun möchte ich, dass der Interrupt erst "aktiviert" wird, wenn eine IF-Bedingung davor erfüllt wurde.
Es soll so ungefähr aussehen, aber ich weiß nicht wie man es richtig im sketch schreibt:
if (Bedingung)
{
Interrupt-abfragen
}
Der Interrupt wird mit einem Taster ausgelöst, aber erst nach erfüllter Bedingung.
Wenn Du den Interrupt erst in Deiner IF setzt?
Wenn an dem Pin zuvor schon Mal ein entsprechendes Signal angelegen hat, kann es sein, daß die ISR direkt aufgerufen wird (weil intern das entsprechende Bit noch gesetzt ist) - Das musst Du ggf. in der ISR abfangen.
Wofür brauchst Du Interrupts??
In >90% der Fälle werden Diese nicht wirklich gebraucht, machen aber Alles komplizierter.
Einen handbetätigten Taster und zeitkritisch im Millisekundenbereich halte ich in 99% der Fälle für einen inneren Widerspruch bzw. einen Ausdruck von Denkfehlern.
Ehrlich.....aus deinen Beschreibungen bzw. Erklärungsversuchen werde ich nicht schlau.
Ich vermute, du weist nicht, was Interrupt bedeutet.
Wenn du einen Interrupt erst nacht einer If-Abfrage erst einliest, geht ds total am Sinn vorbei.
Wenn du dann noch einen Interrupt manuell per Taster auslöst, ist das genauso unsinnig.
Oder ich verstehe tatsächlich nicht was du willst.
Bis in den Millisekundenbereich kann man pollen - wenigstens alle Millisekunde sollte der Arduino die loop() durchlaufen haben, damit Er 'zeitnah' auf 'was auch immer' reagieren kann.
Selbst, wenn Du Dir die Nanosekunden merkst, wann der Taster gedrückt wurde (oder das externe Rechteck-Signal kam) - dadurch wird der Arduino nun auch nicht schneller - die Verarbeitung geschieht in der Regel in der loop() - die ISR ist nur dafür da, zeitkritisches Zeug abzuhandeln, großartige Berechnungen und so Kram gehören dort, normaler Weise, nicht rein.
Vll. wäre es an der Zeit, daß Du damit rausrückst, WAS Du eigentlich vor hast - nicht, was Du aktuell nicht hinbekommst, wie Du denkst, das aktuelle Problem zu umgehen.
Habe die Zeit mit einem Oszi nachgemessen, und die 50ms passen.
Wenn ich nun das UP "Ausgabe" einfach im loop aufrufe funktioniert es, dass die 50ms ausgegeben werden, aber wenn ich das UP per Interrupt aufrufe, gibt er nur einen Impuls mit 3ms aus.
.
.
.
Ausgabe(); //so funktioniert es
.
.
.
.
.
.
attachInterrupt(digitalPinToInterrupt(3), Ausgabe, CHANGE); //so funktioniert es nicht
.
.
.
wisst ihr, warum es mit Interrupt nicht funktioniert??
Das ist jetzt nicht unfreundlich gemeint, aber weißt du warum es mit Interrupt nicht funktioniert? Sollte doch laut dem sketch funktionieren oder?
Ich möchte es einfach mit Interrupt, da das eigentliche Programm viel länger ist, und es wenn möglich auf µSekunden genau sein soll.
Das Programm von vorhin macht eigentlich das gleiche nur viel einfacher.
Ich versteh nur nicht warum es mit einem normalen aufruf funktioniert, und mit Interrupt nicht.
In einer ISR haben Verzögerungen (allgemein langer Code) und vor Allem, weitere ISR-Aufrufe NICHTS verloren.
delay(); basiert auf einem Timer, Der regelmäßig überläuft - Das Ganze ist so programmiert, daß Das alle 4ns (ein 250tel ms) die Variable micros() um 4 erhöht wird und wohl (jetzt kommt Theorie) alle 250x millis() um 1 erhöht wird.
Ob jetzt Überlauf oder Match, der Timer ruft unzählige Male eine eigene ISR auf - und Die sind, wenn man INNERHALB einer ISR ist, gesperrt.
(unzählige Male stimmt nicht ganz ... Er zählt Sie ja)
Wie wichtig ist Es, daß der Impuls DIREKT erzeugt wird?
Du könntest auch den Ausgang auf HIGH schalten und Dir die aktuelle Zeit merken (millis() ).
In loop() prüfst Du, ob die 50ms bereits um sind und schaltest wieder ab.
Da der Interrupt nicht im ms-Takt ausgeführt wird, sondern DIREKT, kann so die Laufzeit aber auf bis zu knapp unter 51ms anwachsen - hier wäre vll. micros() eine Idee.
Dann hättest Du Deinen Interrupt, Dieser würde DIREKT den Ausgang einschalten und in Deiner loop() wartest Du darauf, daß Das wieder abgeschaltet werden kann.
Wobei ich hier immer noch nicht die Notwendigkeit eines Interrupt sehe.
MfG
PS: µs-genau ... langsam wird die Sache brenzlig - Dir ist bewusst, wie lang eine µs ist? Vorhin hatten wir noch 50ms, Die sogar 50ms lang waren.
Bei µs-genau wird Dir ein Interrupt auch nur bedingt helfen - hier müsstest Du in der Taster-ISR den Ausgang HIGH setzen und einen Timer starten, Der so lange läuft, wie Du Das brauchst.
In dieser Timer-ISR müsstest Du dann den Pin wieder LOW schalten.
Mit 16MHz haben wir 1/16tel µs pro Takt - also 16 Takte pro µs.
DAS wird sportlich - Du darfst keine 16 Takte 'verschenken', sonst bist Du von Deiner Ziel-Genauigkeit direkt wieder Welten entfernt.
Sollten Dir ms reichen (wovon ich einfach ausgehe, die Nasa würde wohl nicht hier anfragen und mir wäre unwohl, wenn der neue Rover aufgrund meines Post 'da oben' plötzlich verreckt), solltest Du nicht über µs schwadronieren.
Vereinfacht kann man also sagen, dass man im Interruptprogramm kein Delay ausführen kann.
Und nur nochmal zur wiederholung ob ich es richtig verstanden habe:
Ich könnte im Interruptprogramm den Pin auf HIGH schalten und im loop mitzählen, wie lange der schon auf High ist. Sobald die 50ms erreicht sind schalte ich den Pin wieder auf Low.