PaulStoffregen / FreqMeasureMulti

Measures the elapsed time during each cycle of up to 8 input frequencies.
34 stars 9 forks source link

Version 0.22 frequency is half what it was in 0.1 (which was correct) #3

Closed pauln82 closed 6 years ago

pauln82 commented 8 years ago

Running on Teensy LC FreqMeasureMulti on pin 23. Was returning correct value from test square wave generator under v 0.1. Re-flashed after updating library without changing any code, and now incorrectly returns exactly half the frequency.

pauln82 commented 8 years ago

It appears that specifying the mode FREQMEASUREMULTI_SPACE_ONLY returns the same value as v0.1. I think it would be sensible to make this value the default so that the behaviour is consistent across versions. Otherwise this additional level of control is actually very welcome! :-)

ghost commented 8 years ago

Thank you for pointing that out. Can not reproduce that issue on Teensy 3.1/3.2 where the default mode (FREQMEASUREMULTI_RAISING) returns correct data (double checked with an oscilloscope and with the raw tick count). Example: with FREQMEASUREMULTI_RAISING, FREQMEASUREMULTI_FALLING, and FREQMEASUREMULTI_INTERLEAVE, I read 38755 ticks, and get a display of 1238.55Hz which corresponds perfectly (F_BUS is 48MHz). With FREQMEASUREMULTI_SPACE_ONLY I get 19151 ticks and with FREQMEASUREMULTI_MARK_ONLY I get 19604 ticks which corresponds to the 38755 ticks of the full period. There is no sense in converting only the MARK or only the SPACE tick count (which both describe only a part of the full signal period) into a frequency. Before I order a Teensy LC for further testing, please write back with more details: The frequency which you tried to measure (verified with an external frequency counter), the raw tick counts which you get in the different modes mentioned above, and their respective results after the countToFrequency() conversion.

ghost commented 8 years ago

Being unfortunately still without further details from pauln82, I ordered a Teensy LC last weekend for further tests

MikeR7 commented 6 years ago

i just stumbled across the same problem with a TeensyLC. I connected the 6 valid pins to the same frequency source and found that RAISING, FALLING and INTERLEAVE all report exactly half the correct value (confirmed with an independent frequency measurement, and also confirmed with the example FreqMeasure sketch on pin16).

here is the output of one Serial.print against a measured 905.5Hz signal (approx 60% mark space ratio) using each of the modes:

452.83,24168224.00,228, 452.83,24168224.00,228, 452.83, 905.66,12084116.00,228, 905.66, 905.66

`/* FreqMeasureMulti - Example with serial output http://www.pjrc.com/teensy/td_libs_FreqMeasure.html

This example code is in the public domain. */

include

// Measure 3 frequencies at the same time! :-) FreqMeasureMulti freq1; FreqMeasureMulti freq2; FreqMeasureMulti freq3; FreqMeasureMulti freq4; FreqMeasureMulti freq5; FreqMeasureMulti freq6;

void setup() { Serial.begin(57600); while (!Serial) ; // wait for Arduino Serial Monitor delay(10); Serial.println("FreqMeasureMulti Begin"); delay(10); freq1.begin(6, FREQMEASUREMULTI_RAISING); freq2.begin(9, FREQMEASUREMULTI_FALLING); freq3.begin(10, FREQMEASUREMULTI_INTERLEAVE); freq4.begin(20, FREQMEASUREMULTI_SPACE_ONLY); freq5.begin(22, FREQMEASUREMULTI_MARK_ONLY); freq6.begin(23, FREQMEASUREMULTI_ALTERNATE); }

float sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0; int count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0, count6 = 0; elapsedMillis timeout;

void loop() { if (freq1.available()) { sum1 = sum1 + freq1.read(); count1 = count1 + 1; } if (freq2.available()) { sum2 = sum2 + freq2.read(); count2 = count2 + 1; } if (freq3.available()) { sum3 = sum3 + freq3.read(); count3 = count3 + 1; } if (freq4.available()) { sum4 = sum4 + freq4.read(); count4 = count4 + 1; } if (freq5.available()) { sum5 = sum5 + freq5.read(); count5 = count5 + 1; } if (freq6.available()) { sum6 = sum6 + freq6.read(); count6 = count6 + 1; } // print results every half second if (timeout > 500) { if (count1 > 0) { Serial.print(freq1.countToFrequency(sum1 / count1)); Serial.print(","); Serial.print(sum1); Serial.print(","); Serial.print(count1); } else { Serial.print("(no pulses)"); } Serial.print(", "); if (count2 > 0) { Serial.print(freq2.countToFrequency(sum2 / count2)); Serial.print(","); Serial.print(sum2); Serial.print(","); Serial.print(count2); } else { Serial.print("(no pulses)"); } Serial.print(", "); if (count3 > 0) { Serial.print(freq3.countToFrequency(sum3 / count3)); } else { Serial.print("(no pulses)"); } Serial.print(", "); if (count4 > 0) { Serial.print(freq4.countToFrequency(sum4 / count4)); Serial.print(","); Serial.print(sum4); Serial.print(","); Serial.print(count4); } else { Serial.print("(no pulses)"); } Serial.print(", "); if (count5 > 0) { Serial.print(freq5.countToFrequency(sum5 / count5)); } else { Serial.print("(no pulses)"); } Serial.print(", "); if (count6 > 0) { Serial.print(freq6.countToFrequency(sum6 / count6)); } else { Serial.print("(no pulses)"); } Serial.println(); sum1 = 0; sum2 = 0; sum3 = 0; sum4 = 0; sum5 = 0; sum6 = 0; count1 = 0; count2 = 0; count3 = 0; count4 = 0; count5 = 0; count6 = 0; timeout = 0; } }`

Theremingenieur commented 6 years ago

Sh...t! I'll try to dig into that in the next days. The problem is most probably that the Teensy LC timers are clocked from a different source (F_PLL instead of F_BUS) than the Teensy 3.x timers. Please be patient and use x 2 as a workaround for the moment.

MikeR7 commented 6 years ago

Haha, thanks, will look out for an answer :)

I checked with a Teensy3.2 at 72MHz today - that reads accurately for RAISING and FALLING up to approx 60kHz, then as the frequency increases above 75kHz, the FALLING stays accurate, but the RAISING drops to 0.5 value... Maybe this is linked in some way?

ghost commented 6 years ago

There is nothing linked... The FreqMeasure and FreqMeasureMulti libraries don't basically not measure frequencies but pulse widths, counting clock ticks while high and low. For higher frequencies, that becomes atrociously imprecise, because of the rough and rougher quantization of the shorter and shorter pulse width by these clock ticks and interrupt latency comes into play. That's why on the PJRC website for the FreqMeasure lib, it is clearly stated: FreqCount: best for 1 kHz to 8 MHz FreqMeasure: best for 0.1 Hz to 1 kHz

I found that in reality, on the Teensy 3.x processors with different timer clocking, FreqMeasure and FreqMeasureMulti are well usable up to 10kHz, but the "poor cousin" Teensy LC works only precisely up to 4 or 5kHz when clocked at 48 MHz.

You should not expect a cheap Fiat 500 to pull a 3 tons trailer...

MikeR7 commented 6 years ago

That's fair - I really only need to measure frequency in the range 2Hz - 2kHz, which is perfectly accurate on T3.2 and also on LC when multiplied by 2, so no great problem for me.

manitou48 commented 6 years ago

i just filed the same issue for Teensy LC, but i have a fix, see https://forum.pjrc.com/threads/48812-FreqMeasure-frequencies-off-by-2X

PaulStoffregen commented 6 years ago

I've committed the fix. https://github.com/PaulStoffregen/FreqMeasureMulti/commit/d42db7465a6af8293b2b75a3029fff860e6a30af Thanks!

MikeR7 commented 6 years ago

Perfect, thanks folks!

PaulStoffregen commented 6 years ago

Seems Manitou's fix fully solves this issue. Closing now. Please feel free to reopen if anyone finds a case that still needs work.