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