Strange values while I'm measuring frequency with arduino - Page 1
Forum section: electronics / general

author: dariodario
author_rank: Contributor
timestamp: April 19, 2019, 04:13:45 pm
content: Hi to all,I'm measuring frequency of a sine to square modified voltage. I realized two separate circuit, one with a comparator LM393 and another with a transistor configured as switch. I measure the square wave frequency with an arduino and a good library I found.The sine wave generator is a little ac generator with max 40 volt peak-to-peak, with frequency generated proportional to the speed.Both circuits works quite well. The only problem is that both the circuit are randomly and rarely affected of a sort of "false" measurement.E.g. I'm measuring 350 Hz and sometimes appear 1 measure to 6000Hz. Or on the contrary I'm measuring 350 Hz and sometimes appear 1 measure to 100 Hz, without the motor has changed his velocity (see attached picture). I noticed that the positive spike is the same each time, around 6000 Hz.I asked in another forum too, but at the moment I didn't find a solution.I think is not due to the circuit, once both have the problem. Maybe the generator has some interference or the routine I using (I tested several routines). The only solution would be to filter via software the spike, considering that is impossible for the generator to pass from a value to immediately another not close value.Any suggestion?Thanks.

author: OM222O
author_rank: Frequent Contributor
timestamp: April 19, 2019, 04:49:04 pm
content: instead of using your wave generator, splice off the ends of a 3.5mm headphone jack and use this website to create your sine waves:https://www.szynalski.com/tone-generator/if the amplitude is not large enough for your circuit, you can use a simple inverting op amp with the desired gain to increase it. this is very stable and constant and should allow you to debug the issue. if the same random values appear, then there is something wrong with your sine to square wave converter (which you can eliminate by changing the output of the tone generator website to square wave and connecting it to the arduino directly to measure the frequency and test your code) or in your arduino sketch where you measure the frequency.

author: ajb
author_rank: Super Contributor
timestamp: April 19, 2019, 04:49:34 pm
content: It's possible that your circuit is responding to some occasional noise, although that wouldn't in itself explain the low frequency reading. It's also possible (maybe more likely) that there's an issue with your Arduino program that causes occasional glitches in the computed frequency. Could be an integer overflow, or an issue with non-atomic accesses of timer registers, or an inconveniently-timed interrupt. It's impossible to say without knowing how exactly you've implemented the frequency measurement and preferably seeing your code.If there is an issue with your program, it would be best to find and solve it, but you may still want to add some software filtering to smooth out any jitter in the readings, but of course any sort of filtering is always a compromise between reducing noise and slowing response time, so you'll have to figure out what's tolerable.

author: dariodario
author_rank: Contributor
timestamp: April 20, 2019, 04:32:35 pm
content: Thanks for your answers.Attached is the circuit I'm using. The code I'm using is the gammon code herehttps://www.gammon.com.au/forum/?id=11504&reply=1#reply1I noticed that if I take the out at the pull up resistor R29, the circuit doens't work well, with a lot of incorrect measures (high frequency measure). If I take the out at the end of the series resistor R36 the circuit works well (despite the casual spike I described). Why?So now I have a problem and a doubt!Thanks.

author: duak
author_rank: Super Contributor
timestamp: April 20, 2019, 04:58:35 pm
content: I would add a resistor between the junction of D7 & D9 and the junction of R39 & IC1A-3 to allow the positive feedback from R39 to add hysteresis. I suggest a value of 1K or 2K.I would remove the filter formed by R36 & C4. At this point the input signal should be digital with short rise and fall times. Increasing these times will make the circuit susceptible to electrical noise at the digital threshold levels.

author: Kleinstein
author_rank: Super Contributor
timestamp: April 20, 2019, 06:08:09 pm
content: Quote from: dariodario on April 20, 2019, 04:32:35 pmThe code from the first reply does not take into account the possibility of 2 interrupts (timer overflow and input capture or what is used to get the signal) to happen at nearly the same times. If this happens it is possible to miss an update of the overflow count. This has a chance to happen about 1 in 10000 cases or the like, depending on the code (how many longer commands, length of other ISRs).

author: OM222O
author_rank: Frequent Contributor
timestamp: April 20, 2019, 06:26:18 pm
content: That circuit is way too complicated! Just used a schmitt trigger for your conversion. 1 op amp and 2 resistors is all you need. As I said you can test your code using a website to generate your tones and see if there are random readings in that as well or not

author: dariodario
author_rank: Contributor
timestamp: April 22, 2019, 10:41:35 pm
content: Duak: Thanks, I added a 1.8K resistors and tomorrow I will check if there still are "spikes" in the measurement. Today I noticed that although this resistor, the output still need to be picked out at the end of the series R36-C4 to be reliable in terms of mesurement. A little more investigation and I noticed that it was not the R36 resistor that is changing the game, but the C4! In fact, I removed the R36 and connected C4 to ground at the pull-up resistor junction with the pin 1. And the things worked well (I have to check in detail the presence of the "spikes"). Also a C4=100nF was good. How can be explained this? (in the gammon routine I tried both FALLING and RISING option) in the interrupt definition.OM2220: The circuit I posted should be a "true" schmitt trigger with a comparator instead of an op-amp, from what is my limited knowdledge. I need to use a single power supply and not dual only 5V or 12V. I have a TL081, can you suggest me how to connect it with 2 resistor? Thanks. I would like to try the generated signal in the website directly in the arduino input, but it need at lest >3V to be discriminated as high level. I measured about 1V, so I would need to amplificate etc. etc.. I will try instead the sine wave as input at the comparator to see if the noise (that produces the spikes) is directly generated form the ac generator (it is a speed sensor connected to a washing machine motor driving axle).Kleinstain: At the moment no other routine are run in my code, only the gammon frequency routine. So only one (visible to me) interrupt is generated. I instead was thinking at the fact that the Serial library could get some delay that disturb the capturing time code. I could copy the frequency values in a long array and then print it in a text file at the end of the program, avoiding the Serial library load. What do you thinks.Regards.

author: OM222O
author_rank: Frequent Contributor
timestamp: April 22, 2019, 11:12:45 pm
content: You just need to drive the Vref point with a voltage rather than ground to change the characteristics of the Schmidt trigger ( can be created with a voltage divider that is buffered by an op amp(you can ignore the buffer but there might be weird side effects when doing so), so you need a dual op amp package which is fairly easy to get (MCP6002 is a common example). Here is an example where the op amp is fed from 5v and 0v (double click on it to edit) and the input is a 5v peak to peak sine wave with 2.5v DC offset (doesn't go below 0v):http://tinyurl.com/y37wbctjif your input sine wave is not uni polar (goes above and below 0v) then you can connect the Vref point directly to ground and it would still work, but the duty cycle of the wave will change. however if you only trigger on a rising edge (or only on a falling edge) then the period remains the same and you shouldn't have any issues measuring the frequency. here is the same simulation of the 5v peak to peak sine wave with 0 dc offset and Vref connected to ground. op amp is still only powered from 5v and 0v:http://tinyurl.com/y4uw644yHowever in practical applications an input should never go below the supply rails as it can damage the op amp, so it's advised to add the DC offset to it. let me know if your sine wave is bi polar (going positive and negative compared to ground) so that I can change the circuit to a better one.(Also for the generated tone from the website, you can simply use an inverting amplifier to increase the amplitude. we don't care about audio quality here as the noise is very small (although audible if you actually connect headphones, which is not what you want to do) so if you need a gain of 3 (boosting 1v to 3v), use a 68k and a 22k resistor to get a gain of 3.1)

author: dariodario
author_rank: Contributor
timestamp: April 23, 2019, 02:55:35 pm
content: Yes OM2220, the sine wave is bipolar and the voltage is not fixed but variable form 0 to about 40 Volt peak-to-peak. That's because I added the two diodes. One eliminate the negative wave part (-0,3 volt still remain) and another to cut the positive to 5.3 Volt about. Thanks for your suggestion.With the circuit updated with the resistor as Duak suggestion: Unfortunately the circuit whitout the C4 still continue to do crazy things. Attached you can see the generator turning to produce 100-200 Hz and the measures going upper and lower (Y-axis) up to 120 kHz :-)!!

author: OM222O
author_rank: Frequent Contributor
timestamp: April 23, 2019, 05:01:36 pm
content: you can try eliminating the negative half of the cycle using a diode and a high value resistor like so:http://tinyurl.com/y3hggk54this will not affect frequency measurement if you stay consistent and measure time between rising edges (or falling edges but not both! just pick one).as you can see the green signal is the input which goes from -20 to +20v but the red line which is after the diode, clips out the negative half of the cycle. try this one and let me know how it performs. any cheap diodes should be fine and your resistors don't have to be exact either.Edit: how did your code work when testing with square pulses generated by a computer? did it have random readings as well?

author: TonyStewart
author_rank: Contributor
timestamp: April 23, 2019, 06:29:57 pm
content: Your Op Amp low pass filter T= 0.5 us compared to signal period ~ 3msMaybe there is stray ground noise between signal and Arduino and could be routed with twisted pair.I don't know your Arduino max logic input range will accept 5V or if it is clamped to 3.3V.Increasing R36 to 100k with 4n7 cap across input of Arduino will shunt noise above 0.5ms rise time. There are many other ways to do this even better.

author: OM222O
author_rank: Frequent Contributor
timestamp: April 23, 2019, 08:36:51 pm
content: the circuit he is using is way too over complicated for the task! it needs just one op amp and 2 resistors (+ 1 diode and 1 extra resistor for the bipolar signal) like I shown in my last post. He still hasn't shared the result of testing just the code either.

author: ebastler
author_rank: Super Contributor
timestamp: April 23, 2019, 08:52:49 pm
content: I am with OM222O here: We still do not know whether the OP is chasing a software bug or spurious signals on the generator's output. It would be highly advisable to test the Arduino code with a clean input signal, as a first step to narrowing down the cause.

author: dariodario
author_rank: Contributor
timestamp: April 23, 2019, 09:32:06 pm
content: I triedhttps://www.szynalski.com/tone-generator/and it is better than an android app you can find on the app store because the output is about 0.5V RMS compared with 0.1-0.2V RMS from my smartphone.I used the sine wave signal to drive the LM393 input and I found that1. The C4 is still necessary to the output to be correctly measured. Why?2. The Spike are still present to the output, so they are not depending on the ac generator I'm using. See below.About the point 2 I found that the spike measurement was generated by something related with the Gammon routine. I changed the routine with a less precise (max allowed frequency is 4kHz) and the problem was almost solved. So now I need to found another library or modify the Gammon one (I don't know how).p.s. While I made this post other answer arrived. So sorry to be not updated.Regards.

author: mikerj
author_rank: Super Contributor
timestamp: April 23, 2019, 09:32:22 pm
content: Quote from: dariodario on April 22, 2019, 10:41:35 pmKleinstein is exactly correct, that code has a nasty race condition since the elapsed time consists of a hardware counter which is read on a rising edge interrupt combined with a timer overflow counter that gets updated in a separate overflow interrupt. Fixing this will need a solution very much like reading a 16 bit timer value on the old PICs that didn't have latches, you read timer and overflow flags in a loop until the most significant part (the overflow) hasn't changed during a single loop.Something like this should work, but note I have not tested this code. This will add a small amount of jitter to the timer reads but it's unavoidable if the race condition is to be fixed.Code:void isr (){unsigned int counter;unsigned char overflow;do {overflow = TIFR1 & bit (TOV1); /* Read the overflow interrupt flag */counter = TCNT1; /* Read the 16 bit hardware timer */} while( overflow != (TIFR1 & bit (TOV1)) ); /* Read the overflow interrupt flag again and keep going if it doesn't match *//* If an overflow has occurred we handle it hereif( overflow ){TIFR1 = bit (TOV1); /* Clear the overflow interrupt flag to prevent double counting */overflowCount++; /* Increment the overflow counter */}....../* Rest of rising edge interrupt code here. */......}

author: OM222O
author_rank: Frequent Contributor
timestamp: April 23, 2019, 10:05:03 pm
content: Quote from: dariodario on April 23, 2019, 09:32:06 pmplease post the code which you are using to measure the frequency. Also try the 3 resistors + diode schmitt trigger which I posted and let me know if it converts sine to square wave like intended.

author: OM222O
author_rank: Frequent Contributor
timestamp: April 24, 2019, 03:03:34 pm
content: Actually you need to cut the pulse on the rising edge as well if your op amp is not powered from 20v. so you need 2 schottky diodes. let me know if you want an updated schematic.

author: dariodario
author_rank: Contributor
timestamp: April 24, 2019, 11:05:32 pm
content: I tried the mikerj code with the PC sine generator and the things go better, but still at the (relatively) high frequency there are some incorrect measures. The big spikes are disappeared now, I attached some examples. I think the PC generator is quite stable although could have some %error, but not variable with the time.I also tried a code that measure the rising edge for 1 sec window, so directly calculate the frequency. This code work almost well with a 0.2% error but it has the downside that I need to wait 1 second to receive the measures, that is a bit too long for my application. Cutting the window measurement to 500ms downgrade the error % as expected. I would need an update measure each 0.2-0.3 second.OM 2220: I cannot send the square wave directly to arduino pin because it expects for 0-5 volt transition (0-about 3V), while the PC generate a 0.5 RMS voltage. I want try your circuit, but I would ask you if the IC I have to use is the (half) LM393 or an op-amp like the TL081 I have. The LM393 has an open collector output.Thanks to all for the help.p.s. I'm seriously think to buy a RIGOL 2 channel scope or the similar Siglent.

author: OM222O
author_rank: Frequent Contributor
timestamp: April 24, 2019, 11:55:16 pm
content: here is the circuit you must use with your sensor input to convert from 40v peak to peak sine, to 5v peak square wave (these are op amps, not comparators, but you should get similar results non the less):http://tinyurl.com/y67wylfvif you want to use the online square wave generator, use this circuit (again an op amp, but it can be a comparator as well):http://tinyurl.com/y5eaqmt7the two resistors near the op amp are selected so the voltage between them is less than the maximum of the input signal. in this case maximum output is 5v, so the voltage across the 10k resistor is 5*(10/110) which is about 0.45v and we know the input has a maximum peak of 0.7v (0.5v rms = 1.4v peak to peak, so it goes from +0.7v to -0.7v). just select those values carefully if you change the input voltage.

author: mikerj
author_rank: Super Contributor
timestamp: April 25, 2019, 10:01:01 am
content: Your results suggest you are getting errors in the range of approximately +-50 to +-60 timer counts (assuming 16MHz AVR clock), a little worse at the lower frequencies and a little better at high frequencies. This suggests a problem with noise on your zero crossing detection.Another flaw in that code is that it measures the period of only a single cycle before calculating frequency and displaying the result. This may be appropriate for low frequency signals, but as the signal frequency increases the resolution of your measurement decreases i.e. a few clock cycles error will give a much greater reported frequency error with a high frequency input signal than a low frequency one. The solution is to average the result over a large number of cycles of the input signal which will reduce the effect of noise induced errors.

author: Peabody
author_rank: Super Contributor
timestamp: April 25, 2019, 02:00:16 pm
content: I don't see in Gammon's code where he disables the Timer0 millis interrupt. Something like this:TIMSK0 &= ~bit(TOIE0); // disable overflow interruptIf not disabled, that could mess things up about every millisecond.

author: mikerj
author_rank: Super Contributor
timestamp: April 26, 2019, 02:06:53 pm
content: Timer1 and it's overflow interrupt runs continuously, there is no need to disable them.

author: Peabody
author_rank: Super Contributor
timestamp: April 26, 2019, 08:26:54 pm
content: Quote from: mikerj on April 26, 2019, 02:06:53 pmYes, that's the timer he's using. But I'm talking about timer0 and its overflow ISR, which is used to increment millis. If that's still running, it seems it could interfere with getting good measurements from timer1.

author: dariodario
author_rank: Contributor
timestamp: April 28, 2019, 05:59:26 pm
content: Hi OM2220,I tested the circuit you proposed with a TL081 and it doen't work. No signal AC signal at the output except a continue component to 4.2 Volt.Note that I'm powering the circuit with a single voltage to +5V.I'm not an expert but from what I read all "normal" OP AMP have a common mode voltage for the input so that the minimum voltage to work has to be > from lower side power supply and upper input < to upper side supply. So for example in my case, the TL081 has to have the input >4 volt if the lower supply is ground (see attached image from the datasheet (11volt with reference 15 volt dual)). The web site tone input is at 0.6 V RMS with value that passing from zero volt!There are the "normal" op amp, the "single supply" and the so called "rail to rail".If you lower the input in your simulation to 1 or 2 volt, the circuit have a different output than the square wave.Regards.

author: OM222O
author_rank: Frequent Contributor
timestamp: April 28, 2019, 06:32:55 pm
content: yes because as I mentioned, you should choose the two resistors carefully. as I said before, use the second version for the website and the first version with your sensor. Also the TL081 which you chose will simply not work at all in this case as It has about 3v swing from each rail (look at the Vom : Maximum Peak Output Voltage Swing). That means at minimum you will need 6 Volts (3 volts above ground and 3 volts below VCC) for it to even operate properly! replace the op amp with the rail to rail ones which you mentioned. you should be able to buy MCP6002 from local suppliers very easily!As you can see the only difference between the two versions of the circuit I have shown is the value of the resistors which I explained how you can choose.I have built and tested this circuit and it works properly. Good luck!