Interrupts funktionieren nicht !!

Hallo Arduino Gemeinde,

ich habe mal wieder ein problem und hoffe ihr könnt mir weiterhelfen

Hier erstmal mein Code:

#include <LiquidCrystal.h>
#define INPUTMODE INPUT    // INPUT oder INPUT_PULLUP
#define BOUNCETIME 10             // maximale Prellzeit in Millisekunden
byte buttonPins[]={18, 19, 20, 21};// Pin-Nummern der angeschlossenen Buttons
#define NUMBUTTONS sizeof(buttonPins) // Anzahl der Buttons (automatisch definiert)
volatile byte buttonState[NUMBUTTONS];  // Speichert den aktuellen HIGH/LOW Status der Pins
byte buttonChange[NUMBUTTONS]; // Speichert Flankenwechsel an den Pins
enum{UNCHANGED,BUTTONUP,BUTTONDOWN};
const int LaserPin=7;
const int Step=53;
const int Dir=52;
const int Enable=51;
const int VCC=9;
const int GND=8;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


void eingabe(){
// Tasterstatus und Flankenwechsel an den Tastern auswerten  
  static unsigned long lastButtonTime; // Zeitstempel, wann die Routine zuletzt durchlief
  memset(buttonChange,0,sizeof(buttonChange)); // Alle alten Flankenwechsel verwerfen
  if (millis()-lastButtonTime<BOUNCETIME) return;  // innerhalb der Prellzeit die Funktion verlassen
  lastButtonTime=millis(); // Zeitstempel der letzten Buttonabfrage aktualisieren
  for (int i=0;i<NUMBUTTONS;i++) 
  {
    byte curState=digitalRead(buttonPins[i]);        // Aktueller Buttonstatus
    if (INPUTMODE==INPUT) curState=!curState; // Vertauschte Logik bei INPPUT_PULLUP
    if (curState!=buttonState[i])                    // Flankenwechsel erkannt
    {
      if (curState==HIGH) buttonChange[i]=BUTTONDOWN;
      else buttonChange[i]=BUTTONUP;
    }
    buttonState[i]=curState;  // den jetzigen Buttonzustand speichern
  }
}


int programRunning=-1; // globale Variable speichert das laufende Programm, -1= kein Programm

void verarbeitung()
{ // Verarbeite Tastendrücke
  for (int i=0;i<NUMBUTTONS;i++) 
  {
    if (programRunning==i && buttonChange[i]==BUTTONDOWN) // wenn Programm läuft und Taster gedrückt
      programRunning=-1; // Programm aus
    else if (programRunning<0 && buttonChange[i]==BUTTONDOWN) // wenn kein Programm läuft und Taster gedrückt
      programRunning=i; // laufendes Programm setzen
  }
  // Verarbeite laufendes Programm
  switch (programRunning)
  {
    case 0:
      digitalWrite(LaserPin,HIGH);
      MotorSpeed1();
      break;  
    case 1:
      digitalWrite(LaserPin,HIGH);
      MotorSpeed2();
      break;  
    case 2:
      digitalWrite(LaserPin,HIGH);
      MotorSpeed3();
      break;  
    case 3:
      digitalWrite(LaserPin,HIGH);
      MotorSpeed4();
      break;  
    case 4:
      digitalWrite(LaserPin,HIGH);
    
      break;  
    default:
      digitalWrite(LaserPin,LOW);
      MotorAus();
  }  
}

void MotorSpeed1()
{
int SchleifenZaehl=0; //Variable
int MeinDelay=200;  //Frequenz (Schritte)
int SteigendRam=10; //
digitalWrite(VCC,HIGH);
digitalWrite(GND,LOW);

  DDRB =B00000111; 
  PORTB=B00000010;
  while(1)
  {
   if ( SchleifenZaehl==SteigendRam)
  {
    SchleifenZaehl=0;
    if ( SteigendRam < 2000)
    SteigendRam=SteigendRam+5;
  
    if ( MeinDelay >38)    //Fequenz 
    {
      MeinDelay--;
    }
  }
    SchleifenZaehl=SchleifenZaehl+1;
   
   PORTB=PORTB^B00000001;
   delayMicroseconds(MeinDelay);
   
  } 
}

void MotorSpeed2()
{
int SchleifenZaehl=0; //Variable
int MeinDelay=200;  //Frequenz (Schritte)
int SteigendRam=10; //
digitalWrite(VCC,HIGH);
digitalWrite(GND,LOW);

  DDRB =B00000111; 
  PORTB=B00000010;
  while(1)
  {
   if ( SchleifenZaehl==SteigendRam)
  {
    SchleifenZaehl=0;
    if ( SteigendRam < 2000)
    SteigendRam=SteigendRam+5;
  
    if ( MeinDelay >29)    //Fequenz 
    {
      MeinDelay--;
    }
  }
    SchleifenZaehl=SchleifenZaehl+1;
   
   PORTB=PORTB^B00000001;
   delayMicroseconds(MeinDelay);
   
  } 
}
void MotorSpeed3()
{
int SchleifenZaehl=0; //Variable
int MeinDelay=200;  //Frequenz (Schritte)
int SteigendRam=10; //
digitalWrite(VCC,HIGH);
digitalWrite(GND,LOW);

  DDRB =B00000111; 
  PORTB=B00000010;
  while(1)
  {
   if ( SchleifenZaehl==SteigendRam)
  {
    SchleifenZaehl=0;
    if ( SteigendRam < 2000)
    SteigendRam=SteigendRam+5;
  
    if ( MeinDelay >25)    //Fequenz 
    {
      MeinDelay--;
    }
  }
    SchleifenZaehl=SchleifenZaehl+1;
   
   PORTB=PORTB^B00000001;
   delayMicroseconds(MeinDelay);
   
  } 
}
void MotorSpeed4()
{
int SchleifenZaehl=0; //Variable
int MeinDelay=200;  //Frequenz (Schritte)
int SteigendRam=10; //
digitalWrite(VCC,HIGH);
digitalWrite(GND,LOW);

  DDRB =B00000111; 
  PORTB=B00000010;
  while(1)
  {
   if ( SchleifenZaehl==SteigendRam)
  {
    SchleifenZaehl=0;
    if ( SteigendRam < 2000)
    SteigendRam=SteigendRam+5;
  
    if ( MeinDelay >22)    //Fequenz 
    {
      MeinDelay--;
    }
  }
    SchleifenZaehl=SchleifenZaehl+1;
   
   PORTB=PORTB^B00000001;
   delayMicroseconds(MeinDelay);
   
  } 
}
void MotorAus()
{
digitalWrite(VCC,LOW);
digitalWrite(GND,LOW);
}


void ausgabe()
{ // Ausgabe von Programmänderungen als Text (hier: auf Serial)
  static int lastProgram; // Merker für das zuletzt in der Anzeige angezeigte Programm
  // Nur wenn sich das Programm ändert, wird auch die Anzeige neu geschrieben
  if (lastProgram!= programRunning)
  {
    if (programRunning<0)
    {
         lcd.clear();
         lcd.println("Kein Programm");
      //Serial.println("Kein Programm");
    }
    else
    {  
      lcd.clear();
      lcd.print("Programm-");
      //Serial.print("Programm-");
      // Programme zählen von 0 bis 4, angezeigt werden soll aber von 1 bis 4, daher "+1"
      lcd.println(programRunning+1);
      //Serial.println(programRunning+1);
    }
    lastProgram=programRunning;
  }
}


void setup() {
  //Serial.begin(9600);
  attachInterrupt(2,programstop,CHANGE);
  attachInterrupt(3,programstop,CHANGE);
  attachInterrupt(4,programstop,CHANGE);
  attachInterrupt(5,programstop,CHANGE);
  for (int i=0;i<NUMBUTTONS;i++) 
  pinMode(buttonPins[i],INPUTMODE);
  pinMode(LaserPin,OUTPUT);
  lcd.begin(16, 4);
  pinMode(Step,OUTPUT);
  pinMode(Dir,OUTPUT);
  pinMode(Enable,OUTPUT);
  pinMode(VCC,OUTPUT);
  pinMode(GND,OUTPUT);
}

void programstop()
{
  int programRunning=-1;
}

void loop() {
  eingabe();
  verarbeitung();
  ausgabe();
}

Mein Problem ist das ich in der Switch Anweisung Funktionen aufrufe ( MotorSpeed1,2,3,4 ), aus denen ich nicht mehr raus komme.

Das heißt ich drücke einen Taster die Funktion wird aufgerufen und das wars, danach reagiert nichts mehr, kein display kein Taster mehr.

Das Programm ist so geschrieben dass wenn ein programm angewählt ist, kein anderes aktiviert werden kann, bevor das zuvor laufende nicht beendet ist ( nochmaliges drücken des Tasters ).

Ich habe mich informiert und bin davon überzeugt das ich nur aus der Funktion mit einem Interrupt rauskomme.
Ich benutze übrigens einen Arduino MEGA 2560 ( Die Taster sind an Pin 18,19,20,21 )

Habe dies schon ausprobiert, aber es klappt nicht, weiß nur nicht warum, bitte um Hilfe !!

Mit Dank im Vorraus

Chris85:
Habe dies schon ausprobiert, aber es klappt nicht, weiß nur nicht warum, bitte um Hilfe !!

Ich sehe in Deinem Programm auch keine Klappe, was soll da wo "klappen"?

Ich sehe da nur Buttons.
Buttons werden nicht über Interrupts abgefragt.
Trotzdem versuchst Du das.

Wenn man es richtig macht, kann es natürlich auch funktionieren, Buttons über Interrupts abzufragen. Allerdings ist das aufwändig und fehlerträchtig und daher für Programmieranfänger, die sich schon mit einer geradlinig sequentiellen Programmlogik schwer tun, überhaupt nicht zu empfehlen, sich auch noch in nebenläufige Prozesse und deren Synchronisation mit allen möglichen Nebeneffekten wie "dead lock conditions" und "race conditions" auseinander zu setzen, die logisch einwandfrei gehandelt werden müssen, wenn Interrupts zur Anwendung kommen.

Was soll denn das werden?
Beschreib lieber mal was Du machen möchtest!

Hallo,

Du wirst da auch nie rauskommen, weil while(1) { ... } immer gültig ist und Du innerhalb der while keinen Ausstieg hast. Der Interrupt nützt Dir auch nichts, weil der nur eine Variable setzt und danach kehrt der µC zurück in die while wo er vom ISR unterbrochen wurde zurück.

Du mußt die while Bedingung ändern. Solange die gültig ist, bleibt der µC in der while Schleife, wenn die Bedingung nicht mehr gültig ist, springt er raus und macht danach weiter mit folgenden Befehlen im Code.

Auch deklarierst Du mehrfach die Variable programmRunning mit int. Die ist aber global.

Du definierst hier eine neue lokale Variable. Das int muß weg um die globale an der Stelle zu ändern.

void programstop()
{
  int programRunning=-1;
}

Hallo,

Bsp. mit Lösungsansatz, die while Bedingung muß in ihrer Schleife änderbar sein, sonst hast Du wie erlebt eine Endlosschleife.

void MotorSpeed1()
{
int SchleifenZaehl=0; //Variable
int MeinDelay=200;  //Frequenz (Schritte)
int SteigendRam=10; //
digitalWrite(VCC,HIGH);
digitalWrite(GND,LOW);

  DDRB =B00000111;
  PORTB=B00000010;
  while( ZustandTaster1 == HIGH )  {
	  
   Abfrage des Tasterzustandes ... wenn der LOW ist, wird while verlassen	  
 
   if ( SchleifenZaehl==SteigendRam)
  {
    SchleifenZaehl=0;
    if ( SteigendRam < 2000)
    SteigendRam=SteigendRam+5;
 
    if ( MeinDelay >38)    //Fequenz
    {
      MeinDelay--;
    }
  }
    SchleifenZaehl=SchleifenZaehl+1;
   
   PORTB=PORTB^B00000001;
   delayMicroseconds(MeinDelay);
   
  }
}

Also ich möchte einfach irgendwie aus der Funktion rauskommen um dann nochmal in einen anderes Programm springen zukönnen.
Wie baue ich diese while schleife am besten um das ich rauskomme ( also das wenn ich nochmal den Taster drücke, die funktion beendet wird, so ist es ja im programm code vorgesehen )

Nur wie bewerkstellige ich das am besten ?
Also Interrupts sind zu schwierig, welche Wege gibt es noch die funktionieren würden ??

Wäre super wenn ihr mir beispiele geben würdet

Vielen Vielen Dank im Vorraus :slight_smile:

Chris85:
Wie baue ich diese while schleife am besten um das ich rauskomme ( also das wenn ich nochmal den Taster drücke, die funktion beendet wird, so ist es ja im programm code vorgesehen )

Die Buttons werden in der loop() Funktion abgefragt, durch Aufrufen der Funktion input().

Wenn Dein "Programm" zwischen den Buttonabfragen etwas machen soll, dann am besten

  • keine Schleifen
  • und schon gar keine Endlosschleifen

Dein Programm sollte stattdessen Funktionen aufrufen, die zu jedem Zeitpunkt dann genau das machen, was sie zu diesem Zeitpunkt machen sollen. Kooperatives Multitasking.

Dazu muß Dein Programm wissen, was wann zu welchem Zeitpunkt zu tun ist, und ob dieser Zeitpunkt nun erreicht ist oder noch nicht. Und wenn das ein längerdauernder Vorgang ist, bei dem zu verschiedenen Zeitpunkten verschiedene Dinge zu tun sind, dann ist die Ablauflogik NICHT

void tuWasAuchImmer()
{
  while (irgendwas)
  {
    tuWas();
    delay(irgendeineZeit);
  }
}

Sondern Du brauchst eine Funktion, die tausende male pro Sekunde aufgerufen ist mit so einer Logik:

void tuWasAuchImmer()
{
  static unsigned long zuletztWasGetan;
  if (micros()-zuletztWasGetan>=irgendeineZeit)
  {
    zuletztWasGetan=micros();
    tuWas();
  }
}