Author Topic: measuring frequency with a mcu  (Read 3626 times)

0 Members and 1 Guest are viewing this topic.

Offline 97hilfelTopic starter

  • Regular Contributor
  • *
  • Posts: 66
  • Country: it
measuring frequency with a mcu
« on: December 26, 2016, 07:38:48 pm »
hello everyone,
I wanted to measure a frequency with a arduino board, from 10Hz to 50Hz currently I use this concept (the interrupt based one)http://arduino.datamaster2003.com/f-measurements.htm. and I gives me reasonable results at 46hz, but when the frequency goes down it starts do measure strange things like 90Hz (oscilloscope measures 13-20Hz). Does somebody have an Idea what I can do to prevent this behavor?
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14166
  • Country: de
Re: measuring frequency with a mcu
« Reply #1 on: December 26, 2016, 07:47:10 pm »
The problem could be due to an overflow of an 16 bit value. At about 16 Hz you start to get above 65000 µs for a period.
 

Offline 97hilfelTopic starter

  • Regular Contributor
  • *
  • Posts: 66
  • Country: it
Re: measuring frequency with a mcu
« Reply #2 on: December 26, 2016, 07:48:51 pm »
The problem could be due to an overflow of an 16 bit value. At about 16 Hz you start to get above 65000 µs for a period.
This will probably a problem, do you have an Idea how I can solve this problem?
EDIT: I dont get where that becomes a problem, I am using a unsigned long which should go to 4 million and the function micros() should also work with that so I wont become a problem or?
« Last Edit: December 26, 2016, 07:54:20 pm by 97hilfel »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14166
  • Country: de
Re: measuring frequency with a mcu
« Reply #3 on: December 26, 2016, 08:31:58 pm »
Normally the implementation with unsigned long should work. Can you show the actual code used ?
C is sometimes tricky and uses integers in some places as the default resolution.

There is a small chance that there is something wrong with the implementation of the Arduino libs.

A first test would be to give the periode length instead of the frequency - so exclude one more step.
 

Offline xani

  • Frequent Contributor
  • **
  • Posts: 400
Re: measuring frequency with a mcu
« Reply #4 on: December 26, 2016, 08:37:13 pm »
Simplest way to debug it would be to just print measurements, but it looks like you just have overflow somewhere. Do your code handle timer overflows ? You should have timer overflow interrupt handler that adds timer size to your counter every time it overflows
 

Offline orolo

  • Frequent Contributor
  • **
  • Posts: 352
  • Country: es
Re: measuring frequency with a mcu
« Reply #5 on: December 26, 2016, 08:42:10 pm »
Could it be that the input swings so slowly that it spends too much time between high and low? I don't see that much difference between 46Hz and 20Hz, but who knows. If that were the case, something like a schmitt trigger input may solve the issues.
 

Offline 97hilfelTopic starter

  • Regular Contributor
  • *
  • Posts: 66
  • Country: it
Re: measuring frequency with a mcu
« Reply #6 on: December 26, 2016, 09:23:09 pm »
well I did what I didn't wanted to do, I went for the FreqMeaser Library, I am not a huge fan of these libraries mainly because I dont know whats inside... If my code is still relevant it was something in this region:
Code: [Select]

float freq;
float revolution;

void setup(){
 Serial.begin(57600);
 //some inizialisation code
 attachInterrupt(0, fCount(), FALLING);
}

void loop(){

//Some capturning code for the serial interface

 if(mil_cur-mil_pre >= 100){
    unsigned long _duration = duration;
    unsigned long _plsCount = plsCount;
    duration = 0;
    plsCount = 0;
    freq = 1e6 / float(_duration);
    freq = freq * _plsCount;
    revolution = freq * 30;
 }
//Some blink w/o delay code
}

void fCount() {
  unsigned long curMicro = micros();
  duration = duration + (curMicro - preMicro);
  preMicro = curMicro;
  plsCount = plsCount + 1;
}
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14166
  • Country: de
Re: measuring frequency with a mcu
« Reply #7 on: December 26, 2016, 09:48:33 pm »
I could not see a reason for the possible overflow, but there are two other problems in the code:

There is a minute chance that the interrupt occurs during reading the result. So the part of
unsigned long _duration = duration;
unsigned long _plsCount = plsCount;
duration = 0;
plsCount = 0;
should be inside an CLI() SEI() bracket, or a suitable ATOMIC environment.
It is also strange to use milis to decide if the time is long enough and not the actual time.

Variables used in an ISR and outside should be declared as volatile.
So there should be a
volatile unsigned long duration
and so on.

A minor point:
There is no need to use a long variable for the pulse count.

 

Offline danadak

  • Super Contributor
  • ***
  • Posts: 1875
  • Country: us
  • Reactor Operator SSN-583, Retired EE
Re: measuring frequency with a mcu
« Reply #8 on: December 26, 2016, 10:33:55 pm »
If you have questions about a library look at the code in your IDE to see what its
doing.

Regarding measuring time, frequency, this might be useful -


https://www.dropbox.com/sh/prpc74bdga7yijz/AAAeC-Dmmn5sYbWwRrl0-ZUoa?dl=0



Regards, Dana.
Love Cypress PSOC, ATTiny, Bit Slice, OpAmps, Oscilloscopes, and Analog Gurus like Pease, Miller, Widlar, Dobkin, obsessed with being an engineer
 

Offline Seekonk

  • Super Contributor
  • ***
  • Posts: 1938
  • Country: us
Re: measuring frequency with a mcu
« Reply #9 on: December 27, 2016, 04:04:48 am »
What the "L" is going on.  IIRC long is not sufficient. First time a constant entered =0L; is needed to reserve space for the long number.  I use it so infrequently I have to test the code each time. The explanation is pretty poor.
 

Offline 97hilfelTopic starter

  • Regular Contributor
  • *
  • Posts: 66
  • Country: it
Re: measuring frequency with a mcu
« Reply #10 on: December 27, 2016, 05:13:17 pm »
Variables used in an ISR and outside should be declared as volatile.
So there should be a
volatile unsigned long duration
and so on.
well sorry, I just copied it and added the declarations, they are volatile and I just copied wrong, sorry for that,

should be inside an CLI() SEI() bracket, or a suitable ATOMIC environment.
It is also strange to use milis to decide if the time is long enough and not the actual time.

what on earth is a ATIMIC environment? I am really bad at C and I want to start really learning it, every piece of code I write on MCUs is only based on my c# nowledge and the fact that there are no classes in C... Is it possible to write C++ on AVR MCUs?
And for th final prototype I want to go from a AVR to a Microchip MCU or something a little bit more flexible in terms of interrupts I will need a couple more for the final project, something around 5-10 Interrupt capable pins... (maybe I pull out my old assamby knowledge)
 

Offline retrolefty

  • Super Contributor
  • ***
  • Posts: 1648
  • Country: us
  • measurement changes behavior
Re: measuring frequency with a mcu
« Reply #11 on: December 27, 2016, 06:31:40 pm »
Quote
Is it possible to write C++ on AVR MCUs?

 The Arduino IDE already utilizes C++ using the gcc tool chain.

 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: measuring frequency with a mcu
« Reply #12 on: December 27, 2016, 06:40:55 pm »
Variables used in an ISR and outside should be declared as volatile.
So there should be a
volatile unsigned long duration
and so on.
well sorry, I just copied it and added the declarations, they are volatile and I just copied wrong, sorry for that,

should be inside an CLI() SEI() bracket, or a suitable ATOMIC environment.
It is also strange to use milis to decide if the time is long enough and not the actual time.

what on earth is a ATIMIC environment? I am really bad at C and I want to start really learning it, every piece of code I write on MCUs is only based on my c# nowledge and the fact that there are no classes in C... Is it possible to write C++ on AVR MCUs?
And for th final prototype I want to go from a AVR to a Microchip MCU or something a little bit more flexible in terms of interrupts I will need a couple more for the final project, something around 5-10 Interrupt capable pins... (maybe I pull out my old assamby knowledge)
I'll tell you a secret: you are writing C++, when you use the Arduino framework.
So you are free to add your own classes and use C++ constructs (which you are already doing: float(_duration) is not a C cast, rather a float C++ constructor...

As for the Atomic: it goes with the very meaning of the word "something that cannot be cut", in our case a sequence of instructions that cannot (should not) be interrupted, hence the suggestion to bracket it with a disable/enable interrupt couple.

The code you posted is largely incomplete, so it's impossible for me to say whether it should work or not.
But if (as it would appear) you are trying to measure the frequency every 100ms, there's a high probability of errors:
the accumulated time will depend on when in the 100ms sampling interval the interrupt falls.

The closer to 10Hz (=100ms), the higher the error, since duration is reset to zero.
« Last Edit: December 27, 2016, 10:22:18 pm by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: measuring frequency with a mcu
« Reply #13 on: December 27, 2016, 06:44:55 pm »
What the "L" is going on.  IIRC long is not sufficient. First time a constant entered =0L; is needed to reserve space for the long number.  I use it so infrequently I have to test the code each time.
:wtf: What? No need for an initializer to reserve a variable's space.

The explanation is pretty poor.
Here I agree.  >:D
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Online PA0PBZ

  • Super Contributor
  • ***
  • Posts: 5125
  • Country: nl
Re: measuring frequency with a mcu
« Reply #14 on: December 27, 2016, 07:04:04 pm »
I assume you are feeding the board an external signal you want to measure? I'll leave the software comments to the Arduino aficionados but how does the hardware side look? Do you have or create a proper square wave to feed the board?
Keyboard error: Press F1 to continue.
 

Offline 97hilfelTopic starter

  • Regular Contributor
  • *
  • Posts: 66
  • Country: it
Re: measuring frequency with a mcu
« Reply #15 on: December 28, 2016, 09:29:12 am »
Do you have or create a proper square wave to feed the board?
Yes and no, its a square wave in the common therm it comes from an 4 pin fan and is pulled to 5V using a 10k pullup resistor, but the signal is kind a noisy and has peaks ontop, so I added a 1N4007 after that to "cutdown" the high intervals by about 0.7V so I dont risk having peaks on the signal... they are short and I can't measure them and I dont want to roast my arduino... as I already told I am really bad with C and C++... to compensate that I try to bare C++ program now...  To say about the code, I went from my own code to the FreqMeasure Library availale at the PJRC site, but I am as already told not happy with that solution. Did I forgot something?
 

Online PA0PBZ

  • Super Contributor
  • ***
  • Posts: 5125
  • Country: nl
Re: measuring frequency with a mcu
« Reply #16 on: December 28, 2016, 10:48:06 am »
Do you have or create a proper square wave to feed the board?
Yes and no, its a square wave in the common therm it comes from an 4 pin fan and is pulled to 5V using a 10k pullup resistor, but the signal is kind a noisy and has peaks ontop, so I added a 1N4007 after that to "cutdown" the high intervals by about 0.7V so I dont risk having peaks on the signal... they are short and I can't measure them and I dont want to roast my arduino.

Can you show the input signal to the board on a scope screenshot, preferably with a low frequency input (10-20Hz)?
Keyboard error: Press F1 to continue.
 

Offline danadak

  • Super Contributor
  • ***
  • Posts: 1875
  • Country: us
  • Reactor Operator SSN-583, Retired EE
Re: measuring frequency with a mcu
« Reply #17 on: December 28, 2016, 01:28:33 pm »
Maybe next time you tackle this consider using a Cypress PSOC. This allows
you to do this function entirely in hardware. Eg. generate a gate in HW to control
counting, and only after gate period is over get the data with a poll or interrupt.
Eliminates ISR latency, uncertainties.


For me what stands out is -

1) Routability
2) Fast 12 bit SAR A/D and slow 20 bit DelSig
3) DFB (Digital Filter Block) that is dual channel, handle FIR or IIR filters, or DFB
can be used as a GP fast processor block, similar to RISC block
4) MSI logic elements GUI based and/or the UDB Verilog capability. Eg. the FPGA
like capability
5) Onboard Vref
6) IDAC, VDAC, OpAmps (up to 4), comparator, mixer, switch cap, analog mux....
7) LCD,  COM, UART, I2C, I2S, One Wire, SPI, Parallel, LIN, CAN, BLE, USB
9) Custom components capability, create with schematic capture or Verilog
10) DMA to offload processes like filters, COM, Display
11) ARM M0 (PSOC 4) or M3 (PSOC  5LP) or 8051 core(PSOC 3)
12) Extensive clock generation capabilities
13) All components supported by extensive prewritten APIs

https://www.element14.com/community/thread/23736/l/100-projects-in-100-days?displayFullThread=true

http://www.cypress.com/documentation/code-examples/psoc-345-code-examples

Great video library

Attached component list.  A component is an on chip HW resource.

Free GUI design tool with schematic capture, "Creator". Components have rich API library attached
to each component. Compilers free as well.

PSOC 4 is low end of family, consider 5LP parts as well. PSOC 4 also has arduino footprint boards (pioneer) as well

https://www.elektormagazine.com/labs/robot-build-with-cypress-psoc

http://www.cypress.com/products/32-bit-arm-cortex-m-psoc



Regards, Dana.

Love Cypress PSOC, ATTiny, Bit Slice, OpAmps, Oscilloscopes, and Analog Gurus like Pease, Miller, Widlar, Dobkin, obsessed with being an engineer
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf