Verständnissfrage externalInterrupt

Hallo @ all,
Mittlerweile bin ich mit meinem Projekt schon ein ganzes stück vorangeschritten (Zeitverzögerte Auslösung nach Triggerung durch Sensor)

Ich habe jetzt meine Menüstruktur erstellt und kann meine Werte eingeben. Die Verzögerung wird in eine long Variable als Millis geschrieben.

Jetzt möchte ich mit

attacheInterrupt(0,timer,RISING);

auf einen HIGH Pegel an pin 2 warten und dann nach ablauf der voreingestellten Millis einen Ausgang auf HIGH setzen.

Irgendwie scheitert es aber daran den Ausgang HIGH zu setzen. Momentan wird der Sensor mittels Taster Simuliert. Der Ausgang wird erst nach einem 2. mal Drücken auf HIGH gesetzt.

Hier mal der Interrupt

void timer() {           //Funktion zum interrupt
Serial.println(merker);
if(merker==0){startmillis=millis(); merker=1;Serial.print("if-schleife1");}
Serial.println(startmillis);
aktuellemillis=millis();
if(aktuellemillis-startmillis>=verzoegerungMillis){
digitalWrite(ausgang,HIGH);;
millimerker=aktuellemillis;
merker=0;
Serial.println("if-schleife2");

}
}

Durch die Serial.print´s kann ich sehen das ich in die 2. if schleife komme (beim ersten Tastendruck) aber digitalWrite(ausgang,HIGH); wird erst beim 2. druck ausgeführt.

Kann man nun einfach so einen digitalWrite(ausgang,HIGH); im Interrupt ausführen oder kann ich mir nur einen Merker setzen und dann im loop den merker abfragen? Aber das würde ja am sinn vorbei gehen....

Oder habe ich das mit dem Interrupt total falsch interpretiert?

über Antworten währe ich sehr froh.

Danke der Robert

Hallo derRobert
Ein generelles Problem ist das Prellen des Tasters. Dadurch wird die Interupt-Funktion mehrfach aufgerufen.
Eine Lösung ist als erstes in der Funktion den Interupt zu sperren ( mit detachInterrupt(0) ) un am Ende der Funktion wieder aktivieren ( mit attacheInterrupt(0,timer,RISING); )

OK war nicht Dein Problem:
Dein Problem ist daß die timer-Funktion nur bei einer steigenden Flanke des Signals aufgerufen wird. Also genau 1 mal. Die 2. If-Bedingung (Wartezeit ist vergangen) wird erst beim nächsten Aufruf (= zweiter Tastendruck) wieder kontrolloiert.

Du mußt die 2. If- Bedingung in die LOOP() Funktion geben; nur diese wird regelmäßig aufgerufen.

if(aktuellemillis-startmillis >= verzoegerungMillis && merker==1 )
   {
   digitalWrite(ausgang,HIGH);;
   millimerker=aktuellemillis;
   merker=0;
   }

Die Interuptfunktion:

void timer()
      {           //Funktion zum interrupt
          detachInterrupt(0)
Serial.println(merker);
         if(merker==0)
           {
           startmillis=millis(); 
           merker=1;
           Serial.print("if-schleife1");
           }
       attacheInterrupt(0,timer,RISING); 
       }

Es fehlt dann, noch die Kontrolle den Ausgang auf LOW zu setzen.
Grüße Uwe

Hmmm danke erstmal,

gibt es eine Variante das alles im Interrupt zu tun? also schauen ob zeit vergangen und dann ausgang High setzen?

das ausschalten kann meinetwegen in der Loop passieren.
(Das ich das noch einfügen muss ist mir klar aber ich mache alles schritt für schritt und bin ebend bei dem hängen geblieben :wink: )

ich weis jetzt noch nicht was alles noch in meine loop kommt und außerdem sind da ein paar delay()s drinn und ich möchte nicht das die noch zusätzlich zur wartezeit hinzukommen.

oder gibt es eine möglichkeit aus dem interrupt direkt zum entsprechendem befehl zu springen?

Trotzdem danke nochmal für den hinweis das Interrupt nur einmal durchläuft. Das erklärt natürlich das verhalten

So ich habe eben noch ein wenig gelesen....

kann ich mir eine funktion schreiben, wie zum Beispiel "void ausloesen(){}" und bei Interruptaufruf direkt in die Funktion springen?

geht das so einfach? und wird die funktion dann auch mehrmals ausgeführt wenn ich da ne if drinne habe oder eine while merker==1 oder so????

Danke sagt derRobert

EDIT

Also bedingt klappt der Ansatz aber irgendwie habe ich das Gefühl das die Funktion auch nur einmal ausgeführt wird....
Oder habe ich hier einen anderen Fehler gemacht????

attachInterrupt(0,timerInterrupt, RISING);//Interrupt auf digitalpin2 mit funktionsname "timerInterrupt" auf steigende flanke(rising)
}

void timerInterrupt() {           //Funktion zum interrupt
startmillis=millis();
merker=1;
Serial.println("interrupt");
ausloesen();
}
void ausloesen(){
 Serial.println("void ausloesen1");
 while(merker==1){
 if(millis()-startmillis>=verzoegerungMillis){
 digitalWrite(ausgang,HIGH);
   millimerker=aktuellemillis;
 merker=0;
 Serial.println("void ausloesen2");
 }
}
}

Danke und Gruß derRobert

OK die while schleife der Funktion läuft doch unermüdlich...
Nur leider finde ich keine Möglichkeit die vergangene Zeit in der whileshleife zu messen da mir millis() zwar einmal meinen millimerker füllt aber dann nicht mehr erneuert

void timerInterrupt() {           //Funktion zum interrupt
startmillis=millis()+verzoegerungMillis;
merker=1;
Serial.println("interrupt");
ausloesen();
}
void ausloesen(){
 Serial.println("void ausloesen1");
 Serial.println(startmillis);
 while(merker==1){
   Serial.println("whileschleife");
   Serial.println(verzoegerungMillis);
   millimerker=millis();
   Serial.println("MILLIMERKER=");
   Serial.println(millimerker);
   delay(500); [color=#ff0000]das Delay funktioniert auch nicht [/color] :( das sollte mir zeigen was mit 
                                                                                 millimerker passiert
 if(millimerker >= startmillis){

   digitalWrite(ausgang,HIGH);
 delay(1000);
 digitalWrite(ausgang,LOW);
   millimerker=aktuellemillis;
 merker=0;
 Serial.println("void ausloesen2");
}
}
}

kann mir denn jemand sagen woran das liegt? ich verstehe gerade nicht das in der Funktion (bzw der whileschleife) das mit den millis() nicht klappt....

danke sagt derRobert

Dein Merker wird ja nur nach auslösen des Interrupts auf 1 gesetzt und dann bleibt der AVR in der While-Schleife solange der Merker 1 ist und da der merker 1 bleibt, wird auch immerzu die while-schleife ausgeführt da der Merker ja nicht innerhalb der Schleife wieder auf 0 gesetzt wird und er dann die If-Condition prüfen kann.

Schau noch mal in der Reference nach die while-Schleife wird solange ausgeführt bis die Voraussetzung innerhalb unwahr wird. Das heißt die while loop wird dann ständig wiederholt und der Rest der Mainloop bleibt außen vor bis sich die Voraussetzung der while loop halt ändert.

Packe mal die if condition in die while loop dann müsste es funktionieren

Die if ist ja innerhalb der while schleife aber der millimerker der vor if gesetzt wird bekommt nur einmal einen wert zugewiesen und nich bei jedem durchlauf , wie eigentlich gewollt. millis() in der if Bedingung geht auch nicht. Daher der Umweg über millimerker