Implementing a piece of code using interrupt

I am running a DC motor which is triggered by an IR sensor (going to 0), and I want this DC motor to run continuously only for 2.5 to 3 seconds, after which it should stop until the IR sensor goes low again (from high). I have successfully implemented the code without interrupts, but when I try to implement the same with interrupts (to save on power consumption), the timing part (stopping after continuously running for 3 seconds) is not working and the motor continues to run until the IR sensor goes high again.

#include <LowPower.h>


const int out1 = 5; //motor
const int IRSensor = 3; // connect ir sensor to arduino pin 6
const int LED = 6; // conect Led to arduino pin 9
const int Switch = 2;
const int Mspeed = 175;//0-255
const int Mtime =1500;//500-1000
int statusSensor=1;
int switchSensor=1;
unsigned long prevTime;
volatile int count =0;
volatile int count1=0;
volatile int count2 =0;
volatile int count3=0;
volatile int buttonstate=0;
volatile int lastbuttonstate=0;
volatile bool flag=false;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); 
  pinMode(out1,OUTPUT);
  //pinMode(out1,OUTPUT);
  pinMode (IRSensor, INPUT); // sensor pin INPUT
  pinMode (LED, OUTPUT); // Led pin OUTPUT
  pinMode(Switch, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(IRSensor),IRinterrupt,FALLING);
}


void loop() {
  // put your main code here, to run repeatedly:
  LowPower.powerDown(SLEEP_FOREVER , ADC_OFF, BOD_OFF); 
  delay (100);
  if (flag==true){
  //Serial.println("true");  
  switchSensor = digitalRead (Switch);
  //Serial.println ("zloop");
  
  statusSensor = digitalRead (IRSensor);
  //Serial.println (statusSensor);
  if (count1==1) 
  { prevTime = millis();
    Serial.println(prevTime);
  }
  if (millis() - prevTime >= 1000) 
  { doSomethingElse();
    Serial.println("going to else");
  }
  }
  //prevState = digitalRead(IRSensor);
  doSomething();
  
  

}

void IRinterrupt(){
  
   flag=true;
  }

void doSomething(){
  buttonstatus();
  if (statusSensor == 0 and switchSensor == 0 and count3==0){
   
     analogWrite(out1,Mspeed);
     //digitalWrite(out1,HIGH);
     count1=count++;
     Serial.println(count);
     digitalWrite(LED, LOW);
  }
   else if (statusSensor == 0 and switchSensor == 1) {
      
      //digitalWrite(out1,LOW);
      digitalWrite(LED, HIGH);
      analogWrite(out1,0);
      count=0;
      count1=0;
      prevTime = millis();
      }
   else if (statusSensor == 1 and switchSensor == 0) {
      
      //digitalWrite(out1,LOW);
      digitalWrite(LED, LOW);
      analogWrite(out1,0);
      count=0;
      count1=0;
      prevTime = millis();
      }
    else {
      //Serial.println ("ir high");
      //digitalWrite(out1,LOW);
      digitalWrite(LED, HIGH);
      analogWrite(out1,0);
      count=0;
      count1=0;
      prevTime = millis();
      buttonstatus();
      }
} 
void doSomethingElse(){

    
      //Serial.println ("ir high else");
      analogWrite(out1,0);
      count=0;
      count1=0;
      prevTime = millis();
      count2++;
      count3=count2;
    
      //analogWrite(out1,0);
  }

void buttonstatus(){
  buttonstate=digitalRead (IRSensor);
   if (buttonstate != lastbuttonstate) {
    // if the state has changed, 
    if (buttonstate == LOW) {
      count3=0;
    }
    delay(50);
   }
   lastbuttonstate = buttonstate;
}

This code is same as the one without interrupts, except that now if IR sensor goes low, only then a flag is set in the interrupt which will tell the main loop to execute the remaining part of the program.
Can someone please let me know where I am going wrong ?

You don't need to do anything inside your ISR. Once that happens, you code wakes up and continues on right after the power down. Just run the DC motor for 3 seconds and then turn it off and go back to sleep.

look at the example that comes with the library here

Hi Bob,

first interruptservice-routines should have the IRAM_ATTR -attribute
This makes the compiler load the interrupt-service-routine into ram which can be execeuted
much quicker than code stored in the flash-memory.
In this application shortest latency is not nescessary but you should do it.

so the ISR looks like this

void IRAM_ATTR IRinterrupt(){
     flag=true;
  }

The other thing is you never set flag false again.
The flag is a variable and not an IO-pin. The IO-pin goes low/high with electricity feeded from outside
your variable flag must be set false by your code.

What's the reason to use an interrupt here? If your code does not any more than switch on/off the motor
the interrupt is complicating things without a need.

I want to add something else:
you named functions "DoSomething" and do "somethingElse"

I recommend naming functions with a selfexplaining name what the function does.

best regards

Stefan

The code you posted contains a second void setup void loop.
This gives a compiler-error redefinition of setup / llop

StefanL38:
first interruptservice-routines should have the IRAM_ATTR -attribute
This makes the compiler load the interrupt-service-routine into ram which can be execeuted
much quicker than code stored in the flash-memory.

Pretty sure that's an ESP8266 thing. Maybe ESP32 also, but I don't know.

Did OP state that's the processor architecture in-use? I'm guessing no as LowPower library is not compatible.

blh64:
You don't need to do anything inside your ISR. Once that happens, you code wakes up and continues on right after the power down. Just run the DC motor for 3 seconds and then turn it off and go back to sleep.

look at the example that comes with the library here

Thank you. So I dont need to set any flag in my ISR. And as per the example, I need to add the following lines in the loop function, before running the rest of my code in the loop.

    // Allow wake up pin to trigger interrupt on low.
    attachInterrupt(0, wakeUp, LOW);
    
    // Enter power down state with ADC and BOD module disabled.
    // Wake up when wake up pin is low.
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); 
    
    // Disable external pin interrupt on wake up pin.
    detachInterrupt(0);

StefanL38:
Hi Bob,

first interruptservice-routines should have the IRAM_ATTR -attribute
This makes the compiler load the interrupt-service-routine into ram which can be execeuted
much quicker than code stored in the flash-memory.
In this application shortest latency is not nescessary but you should do it.

so the ISR looks like this

void IRAM_ATTR IRinterrupt(){

flag=true;
  }




The other thing is you never set flag false again.
The flag is a variable and not an IO-pin. The IO-pin goes low/high with electricity feeded from outside
your variable flag must be set false by your code.

What's the reason to use an interrupt here? If your code does not any more than switch on/off the motor
the interrupt is complicating things without a need.

I want to add something else:
you named functions "DoSomething" and do "somethingElse"

I recommend naming functions with a selfexplaining name what the function does.

best regards 

Stefan 

The code you posted contains a second void setup void loop. 
This gives a compiler-error redefinition of setup / llop

I want to use interrupts to save on power consumption instead of polling the IR sensor input all the time.