measuring frequency with a mcu - Page 1
Forum section: electronics / beginners

author: 97hilfel
author_rank: Regular Contributor
timestamp: December 26, 2016, 07:38:48 pm
content: 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?

author: Kleinstein
author_rank: Super Contributor
timestamp: December 26, 2016, 07:47:10 pm
content: 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.

author: 97hilfel
author_rank: Regular Contributor
timestamp: December 26, 2016, 07:48:51 pm
content: Quote from: Kleinstein on December 26, 2016, 07:47:10 pmThis 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?

author: Kleinstein
author_rank: Super Contributor
timestamp: December 26, 2016, 08:31:58 pm
content: 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.

author: xani
author_rank: Frequent Contributor
timestamp: December 26, 2016, 08:37:13 pm
content: 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

author: orolo
author_rank: Frequent Contributor
timestamp: December 26, 2016, 08:42:10 pm
content: 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.

author: 97hilfel
author_rank: Regular Contributor
timestamp: December 26, 2016, 09:23:09 pm
content: 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:float freq;float revolution;void setup(){Serial.begin(57600);//some inizialisation codeattachInterrupt(0, fCount(), FALLING);}void loop(){//Some capturning code for the serial interfaceif(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;}

author: Kleinstein
author_rank: Super Contributor
timestamp: December 26, 2016, 09:48:33 pm
content: 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 ofunsigned 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 avolatile unsigned long durationand so on.A minor point:There is no need to use a long variable for the pulse count.

author: danadak
author_rank: Super Contributor
timestamp: December 26, 2016, 10:33:55 pm
content: If you have questions about a library look at the code in your IDE to see what itsdoing.Regarding measuring time, frequency, this might be useful -https://www.dropbox.com/sh/prpc74bdga7yijz/AAAeC-Dmmn5sYbWwRrl0-ZUoa?dl=0Regards, Dana.

author: Seekonk
author_rank: Super Contributor
timestamp: December 27, 2016, 04:04:48 am
content: 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.

author: 97hilfel
author_rank: Regular Contributor
timestamp: December 27, 2016, 05:13:17 pm
content: Quote from: Kleinstein on December 26, 2016, 09:48:33 pmwell sorry, I just copied it and added the declarations, they are volatile and I just copied wrong, sorry for that,Quote from: Kleinstein on December 26, 2016, 09:48:33 pmwhat 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)

author: retrolefty
author_rank: Super Contributor
timestamp: December 27, 2016, 06:31:40 pm
content: QuoteThe Arduino IDE already utilizes C++ using the gcc tool chain.

author: newbrain
author_rank: Super Contributor
timestamp: December 27, 2016, 06:40:55 pm
content: Quote from: 97hilfel on December 27, 2016, 05:13:17 pmI'll tell you a secret: youarewriting 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.

author: newbrain
author_rank: Super Contributor
timestamp: December 27, 2016, 06:44:55 pm
content: Quote from: Seekonk on December 27, 2016, 04:04:48 amWhat? No need for an initializer to reserve a variable's space.Quote from: Seekonk on December 27, 2016, 04:04:48 amHere I agree.

author: PA0PBZ
author_rank: Super Contributor
timestamp: December 27, 2016, 07:04:04 pm
content: 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?

author: 97hilfel
author_rank: Regular Contributor
timestamp: December 28, 2016, 09:29:12 am
content: Quote from: PA0PBZ on December 27, 2016, 07:04:04 pmYes 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?

author: PA0PBZ
author_rank: Super Contributor
timestamp: December 28, 2016, 10:48:06 am
content: Quote from: 97hilfel on December 28, 2016, 09:29:12 amCan you show the input signal to the board on a scope screenshot, preferably with a low frequency input (10-20Hz)?

author: danadak
author_rank: Super Contributor
timestamp: December 28, 2016, 01:28:33 pm
content: Maybe next time you tackle this consider using a Cypress PSOC. This allowsyou to do this function entirely in hardware. Eg. generate a gate in HW to controlcounting, 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) Routability2) Fast 12 bit SAR A/D and slow 20 bit DelSig3) DFB (Digital Filter Block) that is dual channel, handle FIR or IIR filters, or DFBcan be used as a GP fast processor block, similar to RISC block4) MSI logic elements GUI based and/or the UDB Verilog capability. Eg. the FPGAlike capability5) Onboard Vref6) 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, USB9) Custom components capability, create with schematic capture or Verilog10) DMA to offload processes like filters, COM, Display11) ARM M0 (PSOC 4) or M3 (PSOC 5LP) or 8051 core(PSOC 3)12) Extensive clock generation capabilities13) All components supported by extensive prewritten APIshttps://www.element14.com/community/thread/23736/l/100-projects-in-100-days?displayFullThread=truehttp://www.cypress.com/documentation/code-examples/psoc-345-code-examplesGreat video libraryAttached component list. A component is an on chip HW resource.Free GUI design tool with schematic capture, "Creator". Components have rich API library attachedto 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 wellhttps://www.elektormagazine.com/labs/robot-build-with-cypress-psochttp://www.cypress.com/products/32-bit-arm-cortex-m-psocRegards, Dana.