Inactivity timer after signal acquisition

I am making a new topic since my original problem was solved on my previous forum post. I am trying to add an "inactivity timer" such that if the arduino doesn't recieve pulses from the camera for several seconds, a reset command is triggered. I am doing this using the millis() function. Initially I set "oldtime" to millis(). In the loop if oldtime-millis is greater than 3 seconds and pulses have been triggered (>0), the reset command is called. This part of the code works fine. i run some pulses and stop and the reset command is triggered correctly. In my interrupt statement, I am constantly setting oldtime to millis so that the reset won't be triggered while pulses are being aquired. Strangely, even while signal is being recieved, the timer reset is being triggered randomly. Below is example serial output. Above "Timer escape" the first number is oldtime-millis and the second number is pulse. As you can see that number isn't 3000! So i'm not sure why that escape is being triggered since the first part of the if statement isn't being met. Or is this just an issue using millis() for timing purposes? Is there a better timing system I should be using? Thanks again for the help.
Capture

/* defining variables for input parameters*/
/* pin setup for lasers and camera */
int EMCCD_FIRE = 2; 
int LASER552 = 11;
int LASER647 = 12;

String command;
/* setup of frames per cycle. r is red laser and g is green laser. red laser goes first in sequence.*/

int r = 1500;
int g = 200;
/*int v = 2; */
int cycles = 5;
int startFrame = 50;
int stopFrame = startFrame + cycles*(r+g);
int framesPerCycle = r+g;
volatile unsigned long oldtime;
volatile unsigned int phase;
volatile unsigned int pulse; 
volatile boolean ResetPulses = false;

unsigned int oldpulse = 0;

void(* resetFunc) (void) = 0;

void setup() 
{ 
Serial.begin(9600); 
pulse = 0;
oldtime=millis();
pinMode(EMCCD_FIRE, INPUT); 
pinMode(LASER552, OUTPUT);
pinMode(LASER647, OUTPUT);
digitalWrite(LASER552, LOW);
digitalWrite(LASER647, LOW);
attachInterrupt(digitalPinToInterrupt(2), count_pulse, RISING); 
interrupts();
} 
 
void loop() {
  if(Serial.available()) {
    command = Serial.readStringUntil('\n');

    if(command.equals("reset")){
      Serial.print("Reset");
      delay(1000);
      resetFunc();
    }
  }

  printPulses();  // Prints the no of pulses 

  if (ResetPulses) {  // This is the "Reset function"
    Serial.println("Reset pulses to zero!");
    delay(3000); // Just to wait for some time ... in case of unwanted pulses coming in
    pulse = 0;
    oldpulse = 0;
    oldtime = millis();
    ResetPulses = false;
    digitalWrite(LASER647,LOW);
    digitalWrite(LASER552,LOW);
    Serial.println("Ready for the next job ...");
    
  }

  if ((millis()-oldtime) > 3000 && pulse >0) {
    Serial.println(millis()-oldtime);
    Serial.println(pulse);
    Serial.println("Timer escape");
    ResetPulses = true;
  }
}


void printPulses(){
  if (oldpulse != pulse){  // oldpulse makes sure that this is only done once in loop()
    oldpulse = pulse;
    if (pulse % 10 == 0) {  
      Serial.print("Frame number: "); 
      Serial.println(pulse);
      
    } 
  }
}  

void count_pulse() {
  oldtime = millis();
  pulse++; 

  phase = pulse % framesPerCycle;
  
  if (phase >=r && pulse <= framesPerCycle*cycles) {
    digitalWrite(LASER647,LOW);
    digitalWrite(LASER552,HIGH);
   
  }
  else if (phase < r && pulse <= framesPerCycle*cycles) {
    digitalWrite(LASER647,HIGH);
    digitalWrite(LASER552,LOW);
 
  }
  
  else {
    digitalWrite(LASER647,LOW);
    digitalWrite(LASER552,LOW);
    /*resetFunc(); */
    ResetPulses = true;   // Sets the boolean to true if the conditions to reset are met
    
  }
}

When you compare old-time to millis in your if statement, interrupts need to be off or it can change while you're using it. You might want to disable interrupts, copy it and turn them back on and use the copy in the if.

Wildbill's comment holds for "pulse", too. Here is how to ensure that the comparison is not corrupted by the interrupt.

noInterrupts();
int pulse_copy = pulse;
unsigned long oldtime_copy = oldtime;
interrupts();
if (millis() - oldtime_copy > 3000UL and pulse_copy > 0) {

Yep that was the issue. I've tried it with the no interrupts and it's worked perfectly every time. Thanks guys!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.