Using 2 IR Sensors at the same time

Hi, this is my first complicated Arduino project and I'm struggling to see why my 2 IR sensors are reading 2 different RPMs. I'm looking to use 2 IR sensors to read 2 different objects and light the Green led when they are close to the same speed or light the red LED if it is far off. During my test phase I noticed that RPM gives me an accurate and smooth result in real time while RPM02 is much larger and oscillating. The strange thing is I literally copied the same code yet all my troubleshooting (replacing the IR sensors and switching the inputs) shows that there's something wrong with the code.

My code is 95% based on this Youtube video/code: Arduino Tutorial: Tachometer (RPM Counter) - YouTube

Any help would be greatly appreciated!

const byte PulsesPerRevolution = 2;    // Set how many pulses there are on each revolution. Default: 2.
const byte PulsesPerRevolution02 = 2;  // Set how many pulses there are on each revolution. Default: 2.

const unsigned long ZeroTimeout = 300000;  // For high response time, a good value would be 100000.
                                           // For reading very low RPM, a good value would be 300000.
const unsigned long ZeroTimeout02 = 300000;

// Calibration for smoothing RPM:
const byte numReadings = 5;  // Number of samples for smoothing. The higher, the more smoothing, but it's going to
                             // react slower to changes. 1 = no smoothing. Default: 2.
const byte numReadings02 = 5;
/////////////
// Variables:
/////////////

volatile unsigned long LastTimeWeMeasured;                        // Stores the last time we measured a pulse so we can calculate the period.
volatile unsigned long LastTimeWeMeasured02;                      // Stores the last time we measured a pulse so we can calculate the period.
volatile unsigned long PeriodBetweenPulses = ZeroTimeout + 1000;  // Stores the period between pulses in microseconds.
                                                                  // It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
volatile unsigned long PeriodBetweenPulses02 = ZeroTimeout02 + 1000;
volatile unsigned long PeriodAverage = ZeroTimeout + 1000;  // Stores the period between pulses in microseconds in total, if we are taking multiple pulses.
                                                            // It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
volatile unsigned long PeriodAverage02 = ZeroTimeout02 + 1000;
unsigned long FrequencyRaw;  // Calculated frequency, based on the period. This has a lot of extra decimals without the decimal point.
unsigned long FrequencyRaw02;
unsigned long FrequencyReal;    // Frequency without decimals.
unsigned long FrequencyReal02;  // Frequency without decimals.
unsigned long RPM;              // Raw RPM without any processing.
unsigned long RPM02;            // Raw RPM without any processing.
unsigned int PulseCounter = 1;  // Counts the amount of pulse readings we took so we can average multiple pulses before calculating the period.
unsigned int PulseCounter02 = 1;

unsigned long PeriodSum;  // Stores the summation of all the periods to do the average.
unsigned long PeriodSum02;

unsigned long LastTimeCycleMeasure = LastTimeWeMeasured;  // Stores the last time we measure a pulse in that cycle.
unsigned long LastTimeCycleMeasure02 = LastTimeWeMeasured02;


unsigned long CurrentMicros = micros();  // Stores the micros in that cycle.
unsigned long CurrentMicros02 = micros();

unsigned int AmountOfReadings = 1;
unsigned int AmountOfReadings02 = 1;

unsigned int ZeroDebouncingExtra;
unsigned int ZeroDebouncingExtra02;

// Variables for smoothing tachometer:
unsigned long readings[numReadings];      // The input.
unsigned long readings02[numReadings02];  // The input.
unsigned long readIndex;                  // The index of the current reading.
unsigned long readIndex02;                // The index of the current reading.
unsigned long total;                      // The running total.
unsigned long total02;                    // The running total.
unsigned long average;                    // The RPM value after applying the smoothing.
unsigned long average02;                  // The RPM value after applying the smoothing.

// LEDs for Red and Green
#define RLED 9   // Red LED connected to 9
#define GLED 10  //Green LED connected to 10

void setup()  // Start of setup:
{

  Serial.begin(9600);                                              // Begin serial communication.
  attachInterrupt(digitalPinToInterrupt(2), Pulse_Event, RISING);  // Enable interruption pin 2 when going from LOW to HIGH.

  delay(1000);

  Serial.begin(9600);                                                // Begin serial communication.
  attachInterrupt(digitalPinToInterrupt(3), Pulse_Event02, RISING);  // Enable interruption pin 3 when going from LOW to HIGH.

  delay(1000);

  pinMode(RLED, OUTPUT);

  pinMode(GLED, OUTPUT);

}  // End of setup.

void loop()  // Start of loop:
{

  LastTimeCycleMeasure = LastTimeWeMeasured;  // Store the LastTimeWeMeasured in a variable.
  CurrentMicros = micros();                   // Store the micros() in a variable.

  if (CurrentMicros < LastTimeCycleMeasure) {
    LastTimeCycleMeasure = CurrentMicros;
  }

  FrequencyRaw = 10000000000 / PeriodAverage;  // Calculate the frequency using the period between pulses.

  // Detect if pulses stopped or frequency is too low, so we can show 0 Frequency:
  if (PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra) {  // If the pulses are too far apart that we reached the timeout for zero:
    FrequencyRaw = 0;                                                                                                                         // Set frequency as 0.
    ZeroDebouncingExtra = 2000;                                                                                                               // Change the threshold a little so it doesn't bounce.
  } else {
    ZeroDebouncingExtra = 0;  // Reset the threshold to the normal value so it doesn't bounce.
  }
  FrequencyReal = FrequencyRaw / 10000;  // Get frequency without decimals.
                                         // This is not used to calculate RPM but we remove the decimals just in case
                                         // you want to print it.

  // Calculate the RPM:
  RPM = FrequencyRaw / PulsesPerRevolution * 60;  // Frequency divided by amount of pulses per revolution multiply by
                                                  // 60 seconds to get minutes.
  RPM = RPM / 10000;                              // Remove the decimals.

  // Smoothing RPM:
  total = total - readings[readIndex];  // Advance to the next position in the array.
  readings[readIndex] = RPM;            // Takes the value that we are going to smooth.
  total = total + readings[readIndex];  // Add the reading to the total.
  readIndex = readIndex + 1;            // Advance to the next position in the array.

  if (readIndex >= numReadings)  // If we're at the end of the array:
  {
    readIndex = 0;  // Reset array index.
  }
  // Calculate the average:
  average = total / numReadings;  // The average value it's the smoothed result.

  //Serial.print("Period: ");
  //Serial.print(PeriodBetweenPulses);
  //Serial.print("\tReadings: ");
  //Serial.print(AmountOfReadings);
  //Serial.print("\tFrequency: ");
  //Serial.print(FrequencyReal);
  Serial.print("\tRPM: ");
  Serial.print(RPM);
  Serial.print("\tTachometer: ");
  Serial.println(average);

  LastTimeCycleMeasure02 = LastTimeWeMeasured02;  // Store the LastTimeWeMeasured in a variable.
  CurrentMicros02 = micros();                     // Store the micros() in a variable.

  if (CurrentMicros02 < LastTimeCycleMeasure02) {
    LastTimeCycleMeasure02 = CurrentMicros02;
  }

  FrequencyRaw02 = 10000000000 / PeriodAverage02;  // Calculate the frequency using the period between pulses.

  // Detect if pulses stopped or frequency is too low, so we can show 0 Frequency:
  if (PeriodBetweenPulses02 > ZeroTimeout02 - ZeroDebouncingExtra02 || CurrentMicros02 - LastTimeCycleMeasure02 > ZeroTimeout02 - ZeroDebouncingExtra02) {  // If the pulses are too far apart that we reached the timeout for zero:
    FrequencyRaw02 = 0;                                                                                                                                     // Set frequency as 0.
    ZeroDebouncingExtra02 = 2000;                                                                                                                           // Change the threshold a little so it doesn't bounce.
  } else {
    ZeroDebouncingExtra02 = 0;  // Reset the threshold to the normal value so it doesn't bounce.
  }
  FrequencyReal02 = FrequencyRaw02 / 10000;  // Get frequency without decimals.
                                             // This is not used to calculate RPM but we remove the decimals just in case
                                             // you want to print it.

  // Calculate the RPM:
  RPM02 = FrequencyRaw02 / PulsesPerRevolution02 * 60;  // Frequency divided by amount of pulses per revolution multiply by
                                                        // 60 seconds to get minutes.
  RPM02 = RPM02 / 10000;                                // Remove the decimals.

  //Smoothing RPM: Something up with this area makes the first tachometer not reset back to zero
  total02 = total02 - readings02[readIndex02];  // Advance to the next position in the array.
  readings02[readIndex02] = RPM02;              // Takes the value that we are going to smooth.
  total02 = total02 + readings02[readIndex02];  // Add the reading to the total.
  readIndex02 = readIndex02 + 1;                // Advance to the next position in the array.

  if (readIndex02 >= numReadings02)  // If we're at the end of the array:
  {
    readIndex02 = 0;  // Reset array index.
  }
  //Calculate the average:
  average02 = total02 / numReadings02;  // The average value it's the smoothed result.

  //Serial.print("\tPeriod 2: ");
  //Serial.print(PeriodBetweenPulses02);
  //Serial.print("\tReadings 02: ");
  //Serial.print(AmountOfReadings02);
  //Serial.print("\tFrequency 02: ");
  //Serial.print(FrequencyReal02);
  Serial.print("\tRPM 02: ");
  Serial.print(RPM02);
  Serial.print("\tTachometer 02: ");
  Serial.println(average02);

  if (average == average02 || average == (average02 * 1.1) || average == (average02 - (average02 * 0.1))) {
    digitalWrite(GLED, HIGH);  // Turn the LED on
    digitalWrite(RLED, LOW);   // Turn the LED off
  } else {
    digitalWrite(RLED, HIGH);  // Turn the LED on
    digitalWrite(GLED, LOW);   // Turn the LED off
  }


}  // End of loop.

void Pulse_Event()  // The interrupt runs this to calculate the period between pulses:
{
  PeriodBetweenPulses = micros() - LastTimeWeMeasured;  // Current "micros" minus the old "micros" when the last pulse happens.

  LastTimeWeMeasured = micros();         // Stores the current micros so the next time we have a pulse we would have something to compare with.
  if (PulseCounter >= AmountOfReadings)  // If counter for amount of readings reach the set limit:
  {
    PeriodAverage = PeriodSum / AmountOfReadings;                                // Calculate the final period dividing the sum of all readings by the
                                                                                 // amount of readings to get the average.
    PulseCounter = 1;                                                            // Reset the counter to start over. The reset value is 1 because its the minimum setting allowed (1 reading).
    PeriodSum = PeriodBetweenPulses;                                             // Reset PeriodSum to start a new averaging operation.
    int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);  // Remap the period range to the reading range.
    RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);         // Constrain the value so it doesn't go below or above the limits.
    AmountOfReadings = RemapedAmountOfReadings;                                  // Set amount of readings as the remaped value.
  } else {
    PulseCounter++;                               // Increase the counter for amount of readings by 1.
    PeriodSum = PeriodSum + PeriodBetweenPulses;  // Add the periods so later we can average.
  }

}  // End of Pulse_Event.


//Second Tachometer


void Pulse_Event02()  // The interrupt runs this to calculate the period between pulses:
{
  PeriodBetweenPulses02 = micros() - LastTimeWeMeasured02;  // Current "micros" minus the old "micros" when the last pulse happens.

  LastTimeWeMeasured02 = micros();           // Stores the current micros so the next time we have a pulse we would have something to compare with.
  if (PulseCounter02 >= AmountOfReadings02)  // If counter for amount of readings reach the set limit:
  {
    PeriodAverage02 = PeriodSum02 / AmountOfReadings02;                              // Calculate the final period dividing the sum of all readings by the
                                                                                     // amount of readings to get the average.
    PulseCounter02 = 1;                                                              // Reset the counter to start over. The reset value is 1 because its the minimum setting allowed (1 reading).
    PeriodSum02 = PeriodBetweenPulses02;                                             // Reset PeriodSum to start a new averaging operation.
    int RemapedAmountOfReadings02 = map(PeriodBetweenPulses02, 40000, 5000, 1, 10);  // Remap the period range to the reading range.
    RemapedAmountOfReadings02 = constrain(RemapedAmountOfReadings02, 1, 10);         // Constrain the value so it doesn't go below or above the limits.
    AmountOfReadings02 = RemapedAmountOfReadings02;                                  // Set amount of readings as the remaped value.
  } else {
    PulseCounter02++;                                   // Increase the counter for amount of readings by 1.
    PeriodSum02 = PeriodSum02 + PeriodBetweenPulses02;  // Add the periods so later we can average.
  }

}

Welcome to the forum

Don't attach your code, post it here in code tags

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

The code is probably using interrupts to count. You will need one per sensor - have you change the IRQ for the copy/paste version?

Thank you very much I've copied it on now.

yes the first one uses pin 2 and the second one uses pin 3. The board I'm using is an Uno board btw

What happens if you disconnect pin 2 ?

Hi everyone, I figured it out what was wrong. The potentiometer connected to each ir sensor did not match. Therefore one was more sensitive than the other which caused it to not match. I fixed it now. Thank you everyone for the help

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