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;
}