Ich muss In einem Interrupt grosse Delay Zeiten generieren, brauche ca. 1. Stunde und delay zeiten von 1-5 Sekunden zur überwachung einer Brennstoffzelle. Die Zeiten müssen nicht genau sein .
delay Funktioniert ja leider nich. Ich habe hier eine Anleitung gefunden aber leider noch nicht begriffen
Brauchst Du denn wirklich einen Interrupt? Ist der Impuls so kurz, dass Du ihn nicht im normalen loop() erfassen kannst?
Wenn es mit Interrupt gehen soll, dann kann Du das wie im von Dir geposteten Link machen, also im Interrupt ein Flag setzen (Achtung: volatile-Deklaration nicht vergessen) und dieses im loop() wieder abfragen (und natürlich zurücksetzen). Wenn Du Verzögerungen möchtest, würde ich als Flag gleich den Wert von millis() auslesen und setzen, dann kannst Du von dem Wert aus Vergleiche machen. Poste den Code, den Du hast, dann können wir Dir zeigen, wo das eingebaut werden muss.
Den Standby Modus möchte ich komplett in einem Interrupt Programmieren.
Ich schreibe Dir hier einen Teil meines codes.
Im Void Standby sollte ich ein Delay haben vor dem Befehl
digitalWrite(CellPlus, LOW); (Beispiel)
Ich muss wohl den Befehl irq_flag im void loop Programmieren ?!
Danke !
int Taster=7; //Taster
int Zschloss=2; // Zündschloss Auto
int Modus=9; //Fahrmodus /Zyklus oder Full Power
int Led=13; //Kontroll LED
int CellGND= 12; // Autput Cell GND
int CellPlus= 11; // Autput Cell +
int CellCharge=10; // Output Umschalt-Relais 1=Messen 0=Laden
int Messen = A0; // Input Pin für Messzyklus 1,5V=300 3V=600
volatile int Messwert = 0; // variable zum speichern von Input Analog 0
volatile byte irq_flag = 0; // globale variable, "volatile", da in irq verwendet (ist ein muss)
int Modus_Wert = 0; //variable zum speichern von Zyklus oder Full Power
long letzteMillis = 0; // initialisiere Variable fuer den Zeitpunkt der letzten LED-Aktualisierung
long intervall = 20000; // Intervall, in dem die LED blinkt (Millisekunden), nur Beispiel
void setup() {
Serial.begin(9600);
pinMode(Led,OUTPUT); //Kontroll LED Digital Output 13
pinMode(CellGND, OUTPUT); // CellGND Digital Output 12
pinMode(CellPlus, OUTPUT);// CellPlus Digital Output 11
pinMode(CellCharge, OUTPUT);//Umschalt-Relais 1=Messen 0=Laden
pinMode(Zschloss,INPUT); // Zündschloss Digital Input 8
pinMode(Taster,INPUT); // Taster Digital Input 7
pinMode(Modus,INPUT); // Fahrmodus 1=Full Power 2=Zyklus
int letzter_Tasterzustand = LOW;
int led_state = LOW;
attachInterrupt(0, Standby, LOW);
}
void loop() { //Fahrmodus
digitalWrite(CellCharge, LOW);
delay(10);
digitalWrite(CellGND,LOW);
delay(10);
digitalWrite(CellPlus,LOW);
Modus_Wert = digitalRead (Modus);
while (Modus_Wert==HIGH)
{
//if (digitalRead(Zschloss)==LOW)
//{
//break;
//}
digitalWrite(CellGND,HIGH);
delay(1000);
digitalWrite(CellPlus,HIGH);
if (digitalRead(Modus)==LOW)
{
break;
}
}
digitalWrite(CellPlus,LOW);
delay(1000);
digitalWrite(CellGND,LOW);
delay(10);
digitalWrite(CellCharge,LOW);
delay(10);
}
void Standby()//STANDBY LOOP
{
digitalWrite(CellCharge, LOW);
irq_flag = 1000;
if(irq_flag == 10000) {
/* sende den ping */
irq_flag = 0; // ruecksetzen des flags
}
digitalWrite(CellPlus, LOW);
}
Du bist Dir schon im Klaren, was das macht? Der Interrupt-Handler "Standby" wird so lange immer wieder ausgeführt, wie Pin 2 LOW ist. In dieser Zeit wird kein anderer Code ausgeführt. Ist das wirklich das, was Du willst?
Ich gehe mit uwefed einig, dass Du erklären solltest, was der Arduino genau machen soll und welche Bedeutung die Ein- bzw. Ausgänge haben.
Beschreib bitte genau was du machen willst. Hier passen ein paar Begriffe nicht zusammen.
Interrupt -> für Prozesse die Zeitkritisch bearbeitet werden müssen (Reaktion auf Ereignis)
Standby -> Bereitschaftsbetrieb (Ein gerät das darauf wartet, dass es wider Arbeiten soll) meinst du vielleicht Sleep Mode zu Energie sparen?
Wenn ein bestimmter Programmteil für eine bestimmte zeit nicht ausgeführt werden soll dann verwende einfach mills() im loop.
OK ich muss wohl den Code noch weiter erklären.
Ich möchte Im Interrupt eine Standby Zeit (die fest definiert ist!) von ca. 1.Stunde in dieser Zeit soll der Arduino gar nichts machen !!
Nachher wird ( im Interrupt) ein Mess und ev. Ladezyklus ausgeführt. Den habe ich aus dem Code rausgenommen.
Die Standby Void soll aber jederzeit unterbrochen werden können mit Pin 2- Void loop // Fahrmodus.
Der Begriff Standby ist vielleicht etwas verwirrlich gewesen ?
Arduino soll einfach nach abstellen vom Zündschloss Pin 2 ca 1 Stunde gar nichts machen im Void Standby nachher kommt da schon noch ein Programm Code den ich rausgelöscht hab.
Das ist mein Erstes Arduino Proyekt kann sein das es (für einige ) keinen Sinn macht so lange wartezeiten in einen Interrupt zu Programmieren ?!
Erklär bitte warum das in einen Interrupt soll? Das macht keinen Sinn. Ein Interrupt ist dazu da das regulär laufende Progrmm für eine kurze Aktion zu unterbrechen z.B. um auf Tastendrücke oder Impulse reagieren zu können. Wenn du deinen "Standby" im Interrupt machst ist dieser auch nicht unterbrechbar. Dein "Standby" gehört also in den loop. Warum nimmst du den Mess- und Ladezyklus raus? Entscheide dich ob du was machen willst oder nicht. So könnte das Ganze aussehen:
attachInterrupt(0, Fahrmodus, CHANGE );
loop()
{
while (fahrmodus == false && Zeit < 1h )
{-> Mach deinen Mess- und Ladezyklus}
while (fahrmodus == true )
{-> Mach das was du zum fahren brauchst}
}
Fahrmodus(){
if (PIN2 == LOW)
{Fahrmodus = false}
if (PIN2 == HIGH)
{Fahrmodus = true}
Wie gesagt das ist mein erstes Arduino Projekt. Ich dachte mir eben das es so einfacher ist die 2 Programmteile zu schreiben, da der Fahrmodus und der Standbymodus unabhängig voneinander laufen und ich immer durch Pin 2 den Modus wechseln wollte. Dass die Delay Funktion nicht geht im Interrupt wusste ich anfangs eben noch nicht.
Mein Code ist auch noch lange nicht fertig. Ich blieb eben bei diesm Delay problem stehen... Wie ich aber jetzt sehe ist es wohl nicht möglich im Interrupt eine "Verweilzeit" zu Programmieren die dann jederzeit durch PIN 2 unterbrochen werden kann ???
Wie ich aber jetzt sehe ist es wohl nicht möglich im Interrupt eine "Verweilzeit" zu Programmieren die dann jederzeit durch PIN 2 unterbrochen werden kann ???
Nein, das ist so nicht möglich, jedenfalls nicht sinnvoll. Was Du hier brauchst, wird in Programmiererkreisen State Machine genannt. Du hast also verschiedene Zustände und in jedem Zustand existiert dann ein Code-Teil, der definiert, wie sich der Prozessor hier zu verhalten hat. Ein Interrupt-Handler wäre aber ein denkbar schlechter Ansatz, eine solche State Machine zu implementieren.
In Pseudo-Code sähe das dann etwa so aus:
byte status = 0;
uint32_t start_time = 0;
void setup() {
}
void loop() {
if (status == 0) {
// führe Dinge aus
if (button_pushed) {
status = 1; // wechsle in den nächsten Zustand
}
} else if (status == 1) {
start_time = millis();
// hier können andere Dinge ausgeführt werden
if (millis() - starttime > 3600000L) {
// eine Stunde vorüber
status = 0;
}
}
}
Wie kommt Ihr auf das Brett, daß Interrupts nichts für lange Delays sind? Interrupts sind sehr sinnvoll für lange Delays. Vor allem dann wenn man Strom sparen muß. Allerdings ist der Arduino nicht wirklich brauchbar wenn man Strom sparen muß/will.
D.h. Timer einstellen, laufen lassen und dann den Prozessor schlafen legen und nur mit Interrupt aufwachen. Leider kann man mit dem Arduino ohne Tricks keine 1h Delays hinbekommen. Also entweder zusätzlich eine RTC oder per Interrupt immer wieder aufwachen lassen, per Programm weiterzählen und dann wieder schlafen legen.
Weil ich in meinem Code immer wieder Delays von 1-3 Sekunden habe, dachte ich es sei einfacher den "Modus" meiner Brennstoffzelle
mit einem Interrupt zu Programmieren, da der Code ja bei einem Interrupt immer sofort unterbrochen wird.
Danke Psyon für den State Machine Code !
Jetzt muss ich wohl einfach alle Delays in meinem Code durch eine Zählschleife in Milisekunden Programmieren sonst bleibt das Programm ja immer beim Delay hängen und schaltet nicht sofort um wenn ich den Modus (Status) verändere??
Ebenfalls wenn ich das richtig sehe muss in jeder schleife eine Abbruchbedibgung einbauen ?
Ebenfalls wenn ich das richtig sehe muss in jeder schleife eine Abbruchbedibgung einbauen ?
Kontrollen mit millis() ob die Zeit schon vorbei ist geht davon aus, daß die Kontrolle sehr oft gemacht wird (loop()_funktion läuft permanent durch weil nichts gemacht wird. Erklärung für "ganze" Männer: Du schaust alle Minute auf die Uhr, ob die Kartoffeln gekocht sind und stehst erst vom Sofa auf, wenn die Zeit um ist, damit Du das Fußballsiel verfolgen kannst.
Die Kontrolle für die MODUS-Änderung braucht nur einmal in der Schleife sein.
loverise:
Ebenfalls wenn ich das richtig sehe muss in jeder schleife eine Abbruchbedibgung einbauen ?
Ja. Ohne Abbruchbedingung bleibt man sonst ewig in der Schleife -> Endlosschleife. Der loop ist z.B eine Endlosschleife. Der fängt immer wieder von vorn an. Wenn der loop z.B. nur einmal ausgeführt werden soll setzt man am Ende ein while(true) da bleibt der Controller dann drin hängen bis man Reset drückt.
Also ich würde in so einem Fall alles in setup() packen und gar nichts in loop(). Am Ende von loop() mit einer for(;;); Schleife zu stoppen finde ich schräg.