project code of 'if' statements not liking micros() inside;

This is a bit lengthy, but an interesting project, I am creating a drum pad that oscillates up and down for beneficial practice purposes, i have an IR sensor that reads on a cam and goes from high to low at the bottom of the pads oscillation, this is when the player hits the pad, a piezoelectric pressure sensor reads when the player hits the pad, I am using micros() and interrupts to notify when the player hits the pad and when the pad is at the bottom and compare when the player should hit the pad and when they actually hit the pad.

My issue is that in my if statement that is set by a flags from separate interrupts i tell the arduino to read the time with micros() in the statement. When i Serial.println() the values (hit) and (met) in my code, the serial monitor displays random positive and negative numbers going all over the place. i think solving that issue should get the code to work, plz hlp.

#include <LiquidCrystal.h>

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


unsigned long lcdrefresh;
const int pressure = 18;
const int IRstate = 2; 
const int motor = 11; 
int forward = 12; // motor direction on motor driver forward
int reverse = 13; // motor direction on motor driver reverse
const float accuracy=5; // Accuracy of output when below setrpm
const int N = 3; // No. of references per turn
unsigned long prevmillis; // To store time
unsigned long duration;
boolean currentstate; // Current state of IR input scan
boolean prevstate; // State of IR sensor in previous scan

int setrpm;
int rpm; // RPM value

int met; // integer stored as metronome timer
int hit; // integer stored as hit from piezoelectric sensor
int error; // time difference between metronome click and hit of piezoelectric sensor
int errortotal; // number of errors
int errortime; // time since last error occured
volatile boolean flag1; // flag from interrupt of piezo sensor
volatile boolean flag2; // flag from interrupt of IR sensor

void setup()
{
  Serial.begin(9600);
  lcd.begin(16,2);
  prevmillis = 0;
  prevstate = LOW; 
  pinMode(IRstate,INPUT);
  pinMode(pressure,INPUT);
  pinMode(forward,OUTPUT);
  pinMode(reverse,OUTPUT);
  
 setrpm = map(analogRead(A5), 0, 1023, 0, 255); // Read voltage from potentiometer from analog pin 5 to define and scale setrpm.
 
 attachInterrupt(digitalPinToInterrupt(18), N1, RISING); // piezzo sensor attached to pin 18 interrupt declaration
 attachInterrupt(digitalPinToInterrupt(2), N2, FALLING); // IR sensor attached to pin 2 interrupt declaration
 
   }


void loop()
{

if (flag1==1){
  hit = micros();
  flag1 = 2;
}

if (flag2==1){
  met = micros();
  flag2 = 2;
  Serial.println(met);
}

if((flag1==2) && (flag2==2)){ 
  // Serial.println("flagset")  // use this to show that flag1 and flag2 have both been set
  error = abs(hit - met);
  if(error > 10000){            //if the time difference between hit and metronome click is larger than .1 second, add a count to the error total
   errortotal= errortotal+1;
   errortime=micros();
   flag1=0;             // reset flags to zero so if loop is terminated
   flag2=0;
  }
}


// code reading IR sensor and displaying rpm, functioning perfectly fine

   currentstate = digitalRead(IRstate); // Read IR sensor state
 if( prevstate != currentstate) // If there is change in input
   {
     if( currentstate == LOW ) // If input changes only from LOW to HIGH
       {
         duration = ( micros() - prevmillis ); // Time difference between revolution in microsecond
         prevmillis = micros(); // store time for next revolution calculation
         rpm = (60000000/duration); // rpm = (1/ time millis)*1000*1000*60;
       }
   }
 prevstate = currentstate;         // store this scan (prev scan) data for next scan  

  
   
if(errortotal > 5){                // if 5 errors occur, lower speed of motor and reset errortotal to zero
  setrpm = setrpm - 2;
  errortotal=0;
}
if((micros() - errortime) > 5000000){   //if  5 seconds have elapsed since the last error has occured, reset error total to zero
  errortotal=0; 
}




digitalWrite(forward,LOW);
digitalWrite(reverse,HIGH);                                
analogWrite(motor,setrpm);
//Serial.println(error);

  // LCD Display
  
  if( ( millis()-lcdrefresh ) >= 500 )
    {
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("ETOTAL=");
      lcd.print(errortotal);
      lcd.setCursor(0,1);
      lcd.print("RPM = ");
      lcd.print(rpm); 
      lcdrefresh = millis();   
    } 
  
}

// interrupt voids that set a flag to be read by if statements at the begining of the loop.

void N1()         
{
 flag1=1;
}
void N2()
{
 flag2=1;
}

I don't see anything glaringly wrong with the code, so I question the outputs from the sensors and the interrupt triggers.

Can you document the IR and piezo sensors and their outputs?

Have you tried the interrupt pins as INPUT_PULLUP?

For debugging can you separate the performance of the two sensors?

If you just look at the IRsensor met data do the increments in micros match the expected increments from the rpm?

if (flag2==1){
  met = micros();
  flag2 = 2;
  Serial.println(met);
}

Use unsigned longs for reads of millis() and micros(). Your variable, hit, for example, is an int:

int hit;

Use unsigned longs for reads of millis() and micros(). Your variable, hit, for example, is an int:

Good call. I didn't pick that up.

loganfishguide:

 attachInterrupt(digitalPinToInterrupt(18), N1, RISING); // piezzo sensor attached to pin 18 interrupt declaration

A few things:

  • your variable names are confusing: IRstate apparently refers to a pin number, not the state of some IR sensor.
  • you do declare these pins as variable, yet in this line you use pin numbers directly: bad practice, as when you move it to another pin and change the variable, this does not get changed. Can give you a lot of headbanging to get it working again.
  • are you using a Mega? You didn't mention this, but it must be for pin 18 to exist and have an external interrupt available.

loganfishguide:
I am using micros() and interrupts to notify when the player hits the pad ...

Oh-Oh! :astonished:

I suggest you record the value of micros() in the ISR - something like

void N1()         
{
 flag1 = 1;
 isrN1micros = micros();
}

and then in your main code

if (flag1 == 1) {
  noInterrupts(); // essential to pause interrupts while reading a multi-byte variable
    hit = isrN1Micros
    flag1 = 2;
  interrupts()
}

...R