Double the input double the disaster

I'm writing a code that measures frequency/RPM of a motor (1 tick per rev) and a socket (8 ticks per rev). It also measures an analog input from a pressure sensor. So all together I am measuring three things. After measuring these three things I have it printing to the SD card and to the serial monitor. Now that I have given you the general overview of the program let me get to the problem: When I was only taking in one digital input (the RPM of the motor) and the pressure everything ran like a charm, however as soon as I threw in the second digital input for RPM (the RPM of the socket) it flipped out and would either give me super inaccurate and inconsistent results when receiving a constant signal or they would both go to "inf" depending on the delay time that I put between " measureFreqM();" and " measureFreqS();". I know that you can only run one interrupt at a time but if I'm putting a delay between the two interrupt measurements by up to 100 milliseconds shouldn't it be just fine? For more of an idea of what I'm talking about I'll post my code below.

// This code measure the frequency of an incoming 
// square-wave signal using Timer/Counter 1 and the onboard 
// comparator. The signal I am measuring has a duty-cycle of 
// 50% but the code should work regardless of the duty-cycle.
// It should also work for non-square-wave signals so long as
// the signal voltage drops below the bandgap voltage of the
// onboard comparator (approximately 1.1 V) and is sufficiently
// clean to prevent bouncing. 

//Initial setup for SD Card
#include <SPI.h>
#include <SD.h>

//Calling upon file for the clock
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

// A variable to keep track of the number of overflows on 
// Timer/Counter 1.
volatile unsigned int overflows = 0; 

// A variable to keep track of how many rising edges of the 
// signal have been counted.
volatile unsigned long edges = 0; 

// A variable to keep track of the count on Timer/Counter 1
// when I start counting the edges of the signal.
volatile unsigned long tstart = 0;

// A variable to keep track of the count on Timer/Counter 1
// when I stop counting the edges of the signal.
volatile unsigned long tstop = 0;

// A variable to store temporarily store the count on 
// Timer/Counter 1.
volatile unsigned long tnow = 0;

// This specifies how many cycles over which I want to 
// average the frequency.
const unsigned long cycles = 5; 

// A variable to store the currently measured frequency
float frequencyM = 0;
float frequencyS = 0;
/*
  Analog input, analog output, serial output
 
 Reads an analog input pin, maps the result to a range from 0 (0.5v) to 500 (4.5v)
 and uses the result to set the pulsewidth modulation (PWM) of an output pin.
 Also prints the results to the serial monitor.
 
 The circuit:
 * The analog signal is run through pin 0.
   Center pin of the potentiometer goes to the analog pin.
   side pins of the potentiometer go to +5V and ground
 
 */

// These constants won't change.  They're used to give names
// to the pins used:
const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
const int analogOutPin = 13; // Analog output pin that the LED is attached to

int sensorValue = 0;        // value read from the pressure sensor
int outputValue = 0;        // value output to the PWM (analog out)

const int chipSelect = 10;

File dataFile;

void setup(void) {
   
    Serial.begin (9600);
    
     while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1) ;
  }
  Serial.println("card initialized.");
  
  // Open up the file we're going to log to!
  dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (! dataFile) {
    Serial.println("error opening datalog.txt");
    // Wait forever since we cant write data
    while (1) ;
  }
   
    pinMode(7,INPUT); // This is the analog comparator negative input.
    // This is where the input signal enters the Arduino.
    pinMode(2,INPUT); //Same thing but this one is measuring freq2

    SREG = SREG | B10000000; // Enable gobal interrupts. They should 
    // already be enabled but I like to do this out of good measure.

    //Serial.begin(9600); // For printing the frequency to the terminal
    SD.begin();
    
    #ifdef AVR
      Wire.begin();
    #else
      Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
    #endif
      rtc.begin();

    if (! rtc.isrunning()) 
    {
      Serial.println("RTC is NOT running!");
    }
      // following line sets the RTC to the date & time this sketch was compiled
      //rtc.adjust(DateTime(__DATE__, __TIME__));
       DateTime now = rtc.now();
    
    dataFile.print(now.year(), DEC);
    dataFile.print('/');
    dataFile.print(now.month(), DEC);
    dataFile.print('/');
    dataFile.print(now.day(), DEC);
    dataFile.print(' ');
    dataFile.print(now.hour(), DEC);
    dataFile.print(':');
    dataFile.print(now.minute(), DEC);
    dataFile.println();
    
    dataFile.println("Time, Pressure, Freq M, Freq S"); 
   
}  

void loop(void) 
{
    // read the analog in value (160 PSI Pressure Sensor):
    sensorValue = analogRead(analogInPin);            
    // map it to the range of the analog out:
    outputValue = map(sensorValue, 133, 951, 0, 198);  
    // change the analog out value:
    analogWrite(analogOutPin, outputValue);           
    
    measureFreqM();
    delay(100);
    measureFreqS();
    // print the results
    
    dataFile.print(millis()); 
    dataFile.print(", ");   
    dataFile.print(outputValue); 
    dataFile.print(", "); 
    dataFile.print(frequencyM);
    dataFile.print(", ");
    dataFile.println(frequencyS);
    
    
    Serial.print(millis()); 
    Serial.print(", ");   
    Serial.print(outputValue); 
    Serial.print(", "); 
    Serial.print(frequencyM);
    Serial.print(", ");
    Serial.println(frequencyS);

                          
    
    //dataFile.println(dataString);
    dataFile.flush();
    
    
    // wait 2 milliseconds before the next loop
    // for the analog-to-digital converter to settle
    // after the last reading:
    
    delay(2);
}

void measureFreqM(void) 
{
    edges = 0;

    ACSR = ACSR | B01000010; // enable analog comparator interrupt 
    // on failing edge (bit 1) which would actually capture a rising
    // edge of the signal and use the internal bandgap reference
    // voltage as the positive input (bit 6).
    delay(5); // A short wait for bandgap voltage to stabilize.

    overflows = 0;

    TCCR1A = B00000000; // Set Timer/Counter 1 in normal mode where 
    // it will count to 0xFFFF then repeat.
    TIMSK1 = TIMSK1 | B00000001; // Turn on Timer/Counter 1 overflow 
    // interrupt (bit 0).
  
    // Turn on the counter with no prescaler.
    TCCR1B = TCCR1B | B00000001;

    ACSR = ACSR | B00001000; // Enable analog comparator interrupt 
    // (bit 3).
  
    // Calculate the frequency.
    frequencyM = (float)16000000*(float)cycles/(float)(tstop - tstart);
}

void measureFreqS(void) 
{
    edges = 0;

    ACSR = ACSR | B01000010; // enable analog comparator interrupt 
    // on failing edge (bit 1) which would actually capture a rising
    // edge of the signal and use the internal bandgap reference
    // voltage as the positive input (bit 6).
    delay(5); // A short wait for bandgap voltage to stabilize.

    overflows = 0;

    TCCR1A = B00000000; // Set Timer/Counter 1 in normal mode where 
    // it will count to 0xFFFF then repeat.
    TIMSK1 = TIMSK1 | B00000001; // Turn on Timer/Counter 1 overflow 
    // interrupt (bit 0).
  
    // Turn on the counter with no prescaler.
    TCCR1B = TCCR1B | B00000001;

    ACSR = ACSR | B00001000; // Enable analog comparator interrupt 
    // (bit 3).
  
    // Calculate the frequency.
    frequencyS = ((float)16000000*(float)cycles/(float)(tstop - tstart))/8;
}

ISR(TIMER1_OVF_vect)
{
    overflows += 1;
}

ISR(ANALOG_COMP_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{
    tnow = TCNT1; // current time
    edges += 1;
      if (edges == 1)  // Start counting edges. 
      { 
          tstart = overflows*65536 + tnow;      
      }
      else if (edges == cycles + 1)  // Stop counting edges.
      { 
           tstop = overflows*65536 + tnow;
           // Turn off Timer/Counter 1 and the comparator.
           ACSR = 0; //Analog Comparator Control and Status Register set to zero
           TCCR1B = 0;
      }
}

measureFreqM and measureFreqS are identical except for the last line. It seems that they are both measuring the same input. Am I missing something?

The frequency is calculated immediately after enabling the interrupt. Shouldn't you wait for 5 cycles first?

I'm pretty new to Arduino and this is actually my first "complete" code for it. I wrote most of it by taking bit and pieces of other peoples code that I found online or in the example files. I don't fully understand what most of the code does but I know enough to explain the premise. Here is what I am trying to do with that part of the code: I want it to calculate FreqM from digital input 7 and the code I pulled for calculating frequency in general. Secondly I want to calculate FeqS using digital input 2 (or any other port, it doesn't matter much as long as it isn't pin 7 again) and the code for calculating frequency again. If there is some way that the calculations need to be different I'm really not to sure why or how. Basically I need a very easy to understand explanation if you can.

The delay(2) at the end has a nonsensical comment, as you have already delayed (100) before that.\

I don't understand how those MeasureFreq() functions work.

You enable some timers and interrupts and then you calculate a result ?? Is this cycle counting working all the time, or only when the processor is executing these functions ? Where do cycle and tstart and tstop ever get reset ? If you want to initiate cycle counting, don't you have to wait to collect some samples before having a result ? Where does this happen ?

Get rid of the SD card stuff and the RTC stuff and just concentrate on getting the frequency measurement working. When it is, bring back the other stuff.

And can you describe how the interrupt stuff is supposed to work.

What frequency range is the frequency you are trying to measure? Are interrupts necessary?

...R

Here is the code purely for the frequency:

// This code measure the frequency of an incoming 
// square-wave signal using Timer/Counter 1 and the onboard 
// comparator. The signal I am measuring has a duty-cycle of 
// 50% but the code should work regardless of the duty-cycle.
// It should also work for non-square-wave signals so long as
// the signal voltage drops below the bandgap voltage of the
// onboard comparator (approximately 1.1 V) and is sufficiently
// clean to prevent bouncing. 

// A variable to keep track of the number of overflows on 
// Timer/Counter 1.
volatile unsigned int overflows = 0; 

// A variable to keep track of how many rising edges of the 
// signal have been counted.
volatile unsigned long edges = 0; 

// A variable to keep track of the count on Timer/Counter 1
// when I start counting the edges of the signal.
volatile unsigned long tstart = 0;

// A variable to keep track of the count on Timer/Counter 1
// when I stop counting the edges of the signal.
volatile unsigned long tstop = 0;

// A variable to store temporarily store the count on 
// Timer/Counter 1.
volatile unsigned long tnow = 0;

// This specifies how many cycles over which I want to 
// average the frequency.
const unsigned long cycles = 1000; 

// A variable to store the currently measured frequency
float frequency = 0;

void setup(void) {
pinMode(7,INPUT); // This is the analog comparator negative input.
// This is where the input signal enters the Arduino.

SREG = SREG | B10000000; // Enable gobal interrupts. They should 
// already be enabled but I like to do this out of good measure.

Serial.begin(9600); // For printing the frequency to the terminal
}

void loop(void) {
delay(500);
measureFreq();
Serial.println(frequency);
delay(500);
}

void measureFreq(void) {
edges = 0;

ACSR = ACSR | B01000010; // enable analog comparator interrupt 
// on failing edge (bit 1) which would actually capture a rising
// edge of the signal and use the internal bandgap reference
// voltage as the positive input (bit 6).
delay(5); // A short wait for bandgap voltage to stabilize.

overflows = 0;

TCCR1A = B00000000; // Set Timer/Counter 1 in normal mode where 
// it will count to 0xFFFF then repeat.
TIMSK1 = TIMSK1 | B00000001; // Turn on Timer/Counter 1 overflow 
// interrupt (bit 0).

// Turn on the counter with no prescaler.
TCCR1B = TCCR1B | B00000001;

ACSR = ACSR | B00001000; // Enable analog comparator interrupt 
// (bit 3).

while (edges < (cycles+1)) {
// Do nothing.
}

// Calculate the frequency.
frequency = (float)16000000*(float)cycles/(float)(tstop - tstart);

}

ISR(TIMER1_OVF_vect)
{
overflows += 1;
}

ISR(ANALOG_COMP_vect)
{
tnow = TCNT1; // current time
edges += 1;
if (edges == 1) { // Start counting edges.
tstart = overflows*65536 + tnow;
}
else if (edges == cycles + 1) { // Stop counting edges.
tstop = overflows*65536 + tnow;
// Turn off Timer/Counter 1 and the comparator.
ACSR = 0;
TCCR1B = 0;
} 
}

I pulled it from Measuring Signal Frequency with Arduino – Fiz-ix and adapted it into my code. At first I was measuring the frequency of just one input (the motor via a hall effect sensor) then I had to throw in a second calculation for the socket (also via a hall effect sensor). And since I know very little about coding I simply used the same calculation I used for measuring the freq of the motor for measuring the freq of the socket with the addition of dividing it by 8 because the socket has 8 ticks per revolution whereas the motor only has one. Interrupts are entirely necessary and the frequency range doesn't matter all that much because the code that I'm using can measure has high and as low as my freq generate can generate. As for explaining how things work, as I mentioned before, this is my first real code and I didn't write most of it. That's why I need the help :stuck_out_tongue:

TheArduinist:
And since I know very little about coding ...... Interrupts are entirely necessary ........ and the frequency range doesn't matter all that much because the code that I'm using can measure has high and as low as my freq generate can generate

I can't reconcile the first part of this with the other two or the second part with the last part.

If the frequencies are not high then you don't need to use interrupts.

So how about telling us the max and min frequencies that you actually want to be able to read?

And since it took you 3 days to respond it seems a bit cheeky to be posting a bump after 4 hours or so.

...R

Min freq: 0
Max freq: 200 KHz

I suspect the problem is arising from the calculations part of the code. I'm guessing that some of the things it calls on such as: "TCCR1A = B00000000;" or " TIMSK1 = TIMSK1 | B00000001;" might be only accessible through pin 7. If that's the case I'd either have to find a new way to calculate the frequency for the second input or find the corresponding pathways that would do the same thing just set up for a different pin (which is something I would definitely need help with).

I know enough to know that interrupts are necessary. And I'm not trying to be cheeky, I'm trying to get help, I don't care too much who it's from, just need it asap. Also since you don't know the circumstances of my delayed response so please refrain from "cheeky" replies.

Bump

TheArduinist:
you don't know the circumstances of my delayed response so please refrain from "cheeky" replies.

The circumstances are irrelevant. It's inappropriate for you to nag people to respond promptly when you yourself don't respond promptly.

Counting pulses arriving at 200KHz is going to be extremely difficult since you only have a few clock cycles per pulse. However, I'm surprised to see you hitting the hardware like that. Isn't it possible to just trigger an interrupt from the input and have that increment a counter? Reset the counter at regular intervals and the value at the point of resetting divided by the interval gives you the average frequency.