PaulStoffregen / FreqCount

Measures the frequency of a signal by counting the number of pulses during a fixed time.
http://www.pjrc.com/teensy/td_libs_FreqCount.html
142 stars 47 forks source link

Frequency spikes #4

Open kmcpeak opened 8 years ago

kmcpeak commented 8 years ago

Dear Paul,

I am using the FreqCount library with openQCM to measure the frequency of a 6Mhz crystal oscillator. When I run the openQCM code (see below) it works really well except for these strange glitches every 200 secs or so where the frequency spikes (see graph). The openQCM developer is saying this is a FreqCount issue that occurs for crystals > 5Mhz. Have you observed this behavior before for high freq measurements? The output in the image is simply the frequency every 1 sec, no averaging.

`/* LICENSE

// include library for frequency counting

include

// fixed "gate interval" time for counting cycles 1000ms

define GATE 1000

// Thermistor pin

define THERMISTORPIN A1

// // resistance at 25 degrees C

define THERMISTORNOMINAL 10000

// temp. for nominal resistance (almost always 25 C)

define TEMPERATURENOMINAL 25

// how many samples to take and average

define NUMSAMPLES 10

// The beta coefficient of the thermistor (usually 3000-4000)

define BCOEFFICIENT 3950

// the value of the 'other' resistor

define SERIESRESISTOR 10000

// print data to serial port void dataPrint(unsigned long Count, int Temperature){ //Serial.print("RAWMONITOR"); Serial.println(Count); //Serial.print("_"); //Serial.print(Temperature); //Serial.write(255); }

// measure temperature int getTemperature(void){ int i; float average; int samples[NUMSAMPLES]; float thermistorResistance; int Temperature;

// acquire N samples for (i=0; i< NUMSAMPLES; i++) { samples[i] = analogRead(THERMISTORPIN); delay(10); }

// average all the samples out average = 0; for (i=0; i< NUMSAMPLES; i++) { average += samples[i]; } average /= NUMSAMPLES;

// convert the value to resistance thermistorResistance = average * SERIESRESISTOR / (1023 - average);

float steinhart; steinhart = thermistorResistance / THERMISTORNOMINAL; // (R/Ro) steinhart = log(steinhart); // ln(R/Ro) steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro) steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To) steinhart = 1.0 / steinhart; // Invert steinhart -= 273.15; // convert to C

// decimal value Temperature = steinhart * 10; return(Temperature); }

// QCM frequency by counting the number of pulses in a fixed time unsigned long frequency = 0; // thermistor temperature int temperature = 0;

void setup(){ Serial.begin(115200); // Configure the reference voltage used for analog input analogReference(EXTERNAL); // init the frequency counter FreqCount.begin(GATE); }

void loop(){ if (FreqCount.available()) { frequency = FreqCount.read(); // measure QCM frequency temperature = getTemperature(); // measure temperature dataPrint(frequency, temperature); // print data } } `

Thanks a lot for your help!

Regards, Kevin

freqcount_w-openqcm_6mhz-crystal

PaulStoffregen commented 8 years ago

Two questions:

Have you tried running FreqCount's Serial_Output example, and capture it with a program like CoolTerm?

Which hardware are you using? If I try to reproduce this (which would be much more likely if it's reproducible without the other software), this little detail matters greatly...

kmcpeak commented 8 years ago

Paul,

Below is output from FreqCount's Serial_Output captured in TeraTerm and plotted up. This is running on an Arduino Micro (https://www.arduino.cc/en/Main/ArduinoBoardMicro), microcontroller: ATmega32U4. Thanks.

Regards, Kevin

freqcount_serial-output

kmcpeak commented 8 years ago

Paul,

To simplify the setup I used a function generator (Tektronix AFG3022) to input 1,5 and 6 Mhz into the Arduino Micro and an Agilent 53132A counter. Below are plots of FreqCount's Serial_Output and the Agilent counter. Notice the glitches at all frequencies for the Serial_Output. Can you please look into resolving this. Thank you.

Regards, Kevin

1mhz-input_agilent-vs-micro 5mhz-input_agilent-vs-micro 6mhz-input_agilent-vs-micro

PaulStoffregen commented 8 years ago

Each glitch appears to be one higher measurement, followed by one balancing lower one. That's what happens if the counter is read late. The next count makes up the difference.

My guess is the timer0 interrupt for millis() is delaying the acquisition. Please try adding this in setup()

  TIMSK0 &= ~(1 << TOIE0);   //  Disable Timer 0 interrupt
kmcpeak commented 8 years ago

Paul,

Here is the code: `/* FreqCount - Example with serial output

void setup() { TIMSK0 &= ~(1 << TOIE0); // Disable Timer 0 interrupt Serial.begin(57600); FreqCount.begin(1000); }

void loop() { if (FreqCount.available()) { unsigned long count = FreqCount.read(); Serial.println(count); } } ` But the output still has glitches, see image. serial_output_v2_qcm