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.
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?
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.
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 )
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
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");
}
}
}
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....
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