Problem using interrupt on Mega2560

Good day,

I’m making use of the external interrupt (INT0) to switch between two states namely AdjustMode and ScanMode. The interrupt is triggered by a change in state on the INT0 pin, thereafter the status of the pin is read and the correct function is selected depending on the state of the INT0 pin. If the status of the switch changes the first time it goes to the next state, but the state doesn’t change if I flip the switch more than once. Could you please give some guidance as to how to solve this problem?

I’m making use of a SPST switch to change the state of the INT0 pin.

*--------------------------*/
#include <LiquidCrystal.h>;

//Inputs--
int Hor_Home = 10;
int Ver_Home = 11;
int EchoPin = 12;
int LaserPos = A2;
//Interrupts-----------
int ModePin = 2;
volatile int ModeState = LOW;
//Outputs------------
int Hor_Dir = 29;                                          
int Hor_Step = 28;                                         
int Ver_Dir = 25;                                           
int Ver_Step = 24;                                          
int Las_Dir = 27;                                           
int Las_Step = 26;                                         
int Table_Dir = 23;                                         
int Table_Step = 22;                                       

int TrigPin = 13;
int Laser = 3;                                              

//--------------------------------------------------------

int AdjustState = 0;
int ScanState = 0;
int HorizontalLimit;
int VerticalLimit;
int LaserSetPos = 1020;                                  
int LaserPosVal = 0;                                    

long duration;                                             
long distance;  
int  Obj_size;
long HorTurnNum; 
long VerTurnNum;                                          

char ch;
//int ScanState;

//Funtion definitions
void AdjustMode(void);
void HorisontalHome(void);
void VerticalHome(void);
void CheckHeight(void);
void CalcPos(void);
void SetHorPos(void);
void SetVerPos(void);
void AdjComp(void);
void ScanMode(void);
void LaserHome(void);
void ScanProcess(void);
void StartScan(void);
void RotTable(void);
void LaserSmallUp(void);
void LaserBigUp(void);
void LaserSmallDown(void);
void LaserBigDown(void);
//-------------------------

LiquidCrystal lcd(4, 5, 6, 7, 8, 9);                    

void setup() {

//Interrupts-
  attachInterrupt(0, ModeSelect, CHANGE);

//Inputs-----------------
   pinMode(ModePin , INPUT);
   pinMode(Hor_Home , INPUT);     
   pinMode(Ver_Home , INPUT); 
   pinMode(EchoPin, INPUT);                             

//Outputs------------------ 
   pinMode(Hor_Dir , OUTPUT);
   pinMode(Hor_Step , OUTPUT);
   pinMode(Ver_Dir , OUTPUT);
   pinMode(Ver_Step , OUTPUT);
   pinMode(TrigPin, OUTPUT);  
   pinMode(Las_Dir , OUTPUT);
   pinMode(Las_Step , OUTPUT); 
   pinMode(Table_Dir , OUTPUT); 
   pinMode(Table_Step , OUTPUT); 
   pinMode(Laser , OUTPUT);
   
//Output states
   digitalWrite(Hor_Dir, LOW);
   digitalWrite(Hor_Step, LOW);
   digitalWrite(Ver_Dir, LOW);
   digitalWrite(Ver_Step, LOW);
   digitalWrite(Las_Dir, LOW);
   digitalWrite(Las_Step, LOW);
   digitalWrite(Laser, LOW);

//lcd module----------------------------------------------  
  lcd.begin(16, 2);
  lcd.clear();  
  lcd.print("PLMCC 3D Scanner");
  
//Serial Set up-------------------------------------------
Serial.begin (9600);
  

}
//--------------------------------------------------------
void loop() {

 ModeSelect ();
}
//--------------------------------------------------------
//ModeSelect selects between Adjust mode and scan mode
//
//----------------------------------------------------------
void ModeSelect ()
{
  ModeState = digitalRead(ModePin);
  if (ModeState == HIGH)
  {
   AdjustState = 1;
   AdjustMode();             
  }
  
  else if (ModeState == LOW)
  {
   ScanState = 1;
   ScanMode(); 
  }
}

//--------------------------------------------------------------
void AdjustMode()
{
 lcd.setCursor(0, 1);                                            
 lcd.print("Adjust Mode ON");                                   
 delay(5000);                                                    
 lcd.clear();                                                    
 lcd.setCursor(0, 0);
 lcd.print("Adjust Mode ON");                                   
  
  
 switch(AdjustState)
 {
   
   case 1:    
 
    HorisontalHome();
    break;
  
  case 2:
  
    VerticalHome();
    break;
  
  default:
  lcd.clear();                                                    
  lcd.setCursor(0, 0);
  lcd.print("Adjust Mode DONE");
  lcd.setCursor(0, 1);
  lcd.print("Select Scan Mode");
  
 }
}
  //-----------------------------------------------------------
  
   void HorisontalHome()
  {
    lcd.clear();                                                    //Clears the display
    lcd.setCursor(0, 0);
    lcd.print("Adjust Mode ON");
    lcd.setCursor(0, 1);
    lcd.print("Horisontal home");
  
    digitalWrite(Hor_Dir, HIGH);
    digitalWrite(Hor_Step, LOW);
    
    HorizontalLimit = digitalRead(Hor_Home);
   
    while(HorizontalLimit != HIGH)
    {
      digitalWrite(Hor_Step, HIGH);
      delay(1);          
      digitalWrite(Hor_Step, LOW); 
      delay(1);
      HorizontalLimit = digitalRead(Hor_Home);
    } 
 
   digitalWrite(Hor_Dir, HIGH);
   
    AdjustState = 2;   
  }
//---------------------------------------------------------------  
  
  void  VerticalHome()
  {
    lcd.clear();                                                    //Clears the display
    lcd.setCursor(0, 0);
    lcd.print("Adjust Mode ON");
    lcd.setCursor(0, 1);
    lcd.print("Vertical home");
    delay(1000);
    
    digitalWrite(Ver_Dir, LOW);
    digitalWrite(Ver_Step, LOW);
    
    VerticalLimit = digitalRead(Ver_Home);
   
    while(VerticalLimit != HIGH)
    {
      digitalWrite(Ver_Step, HIGH);
      delay(5);         
      digitalWrite(Ver_Step, LOW); 
      delayMicroseconds(5);
      VerticalLimit = digitalRead(Ver_Home);
    } 
 
    AdjustState = 3;   
  }
  

//----------------------------------------------------------------




void ScanMode()
{

 lcd.clear();                                                  //Clears the display
 lcd.setCursor(0, 0);
 lcd.print("PLMCC 3D Scanner");
 lcd.setCursor(0, 1);
 lcd.print("Scan Mode ON");                                    
 
  delay(5000);                                                  //Allows for 5 seconds for the user to see the status of the scanner
  
  switch (ScanState)
  {
    
    case 1:
    
      LaserHome();
      break;
    
    case 2:
    
      ScanProcess();
      break;
    
    default:
    
     lcd.clear();                                                  //Clears the display
     lcd.setCursor(0, 0);
     lcd.print("PLMCC 3D Scanner");
     lcd.setCursor(0, 1);
     lcd.print("Scan Mode ...");   
  }
}
 //----------------------------------------------------------------

void LaserHome()
{
  lcd.clear();                                                  //Clears the display
  lcd.setCursor(0, 0);
  lcd.print("Scan Mode ON"); 
  lcd.setCursor(0, 1);
  lcd.print("Laser home");
  
  LaserPosVal = analogRead(LaserPos);
  
  if (LaserPosVal < LaserSetPos)
  {
    digitalWrite(Las_Dir, LOW);
    
    while (LaserPosVal < LaserSetPos)
    {
    
     digitalWrite(Las_Step, HIGH);
     delay(2);          
     digitalWrite(Las_Step, LOW); 
     delay(2);
    
     LaserPosVal = analogRead(LaserPos);
     
    }
  }
  
  else if (LaserPosVal > LaserSetPos)
  {
     digitalWrite(Las_Dir, HIGH);
     
     while (LaserPosVal > LaserSetPos)
    {
      
     digitalWrite(Las_Step, HIGH);
     delay(2);          
     digitalWrite(Las_Step, LOW); 
     delay(2);
    
     LaserPosVal = analogRead(LaserPos);
     
    }
    
  }
  
  ScanState = 2;
}

//---------------------------------------------------------

void ScanProcess()
{
  while (ScanState == 2)
  {
    if (Serial.available() > 0)
    {
      ch = Serial.read();
      if (ch == 'L')
      {
        digitalWrite(Laser, HIGH);                      //Switches ON laser
      }
      
      else if (ch == 'l')
      {
        digitalWrite(Laser, LOW);                      //Switches OFF laser
      }
      
      else if (ch == 'S')
      {
        StartScan();
      }
      
    }
  }
}
//----------------------------------------------------------
//Rotates  the laser by 60 degrees
//----------------------------------------------------------

void StartScan()
{
  LaserHome();
  
  lcd.clear();                                                  //Clears the display
  lcd.setCursor(0, 0);
  lcd.print("Scan Mode ON"); 
  lcd.setCursor(0, 1);
  lcd.print("Scan in process");
  
  digitalWrite(Laser, HIGH);                      r
  
  digitalWrite(Las_Dir, HIGH);
  
  for (int d = 0; d < 267; d++)      
  {
    digitalWrite(Las_Step, HIGH);
    delay(250);          
    digitalWrite(Las_Step, LOW); 
    delay(250);
  }
  
  digitalWrite(Laser, LOW);                      //Switches OFF laser
  
  digitalWrite(Las_Dir, LOW);
}

The interrupt triggers ModeSelect(), which is doing all kinds of things that are not appropriate in an interrupt service handler.

You can't call delay() in an ISR, for instance. You can't have while loops that could take forever to end. lcd.print() takes a long time, in some cases, and is ill-advised in an ISR.

All the the ISR should do is set the mode - scan or adjust. The loop() function should see that the mode has changed, and react accordingly.