# Measuring sine wave altitude by adc

Discussion in 'Embedded Systems and Microcontrollers' started by soderdaen, Jan 21, 2016.

1. ### soderdaen Thread Starter New Member

Nov 21, 2015
16
1
Hey everyone,

I am currently struggeling in measuring a one way rectified sine wave with my arduino board. I have a function generator which gives me a sine wave. I rectify it by a diode and measure the signal with my adc. No problem so far.
Now I just like to have the maximum point of the sine wave, but my code gives me the right values sometimes, sometimes the wrong values. I know why, but I am not that experienced to solve the programming task here by myself. I am continuosly asking the adc if it has a higher value for me than in the variable "highvalue". If it is, we have a new highvalue, if not than a counter counts up. If that counter reaches 10 I return my highvalue.
The reason why I get wrong values is because of noise or a lack of adc accuracy. Then the counter counts up, but it shouldnt. Or in the half wave that has been cut off there is a little noise that when the upper_halfwave function starts there I will get a 5 in my highvalue and then just zeros out of the adc and in the end my high value is 5.
Can anyone help me out with that ? Here is my code:

Code (Text):
1. int upper_halfwave()
2. {
3.     while(1)
4.     {
7.         {
8.         }
12.         {
14.             counter=0;
15.         }
16.         else
17.         {
18.             counter++;
19.         }
20.         if (counter==10)
21.         {
22.             highvalue=0;
23.             return highvalue;
24.         }
25.     }
26.
27. }

2. ### DickCappels Moderator

Aug 21, 2008
2,785
676
What may be the simplest and most sure solution is placing a capacitor on the diode's output to form a peak detector. Then a large resistor across the capacitor to act as a bleeder will allow tracking as the amplitude of the sine wave is reduced.

About a year ago I implemented code to simulate a diode peak detector and a bleeder resistor in an AVR and after tweaking time constants it worked very nicely.

Yes, the ADC was kept very busy, being run in an interrupt routine that was triggered by a timer. If I recall correctly, I also did some averaging to reduce noise -for example adding together sixteen measurements then shifting the sum shirt right four times to divide by 16, yielding the average.

3. ### soderdaen Thread Starter New Member

Nov 21, 2015
16
1
That is a good idea DickCappels, but unfortunately I need to do it software side for the proejct

4. ### DickCappels Moderator

Aug 21, 2008
2,785
676
I wrote code similar to yours that constantly monitored the input signal, increased the value in a register (like your "highvalue" variable if the ACD gave a reading that was higher than the last recorded "highvalue". A separately timed task would subtract a little; bit from "highvalue" so that the content of "highvalue" dropped, lagging a little, as the peak input value dropped. It simulated the action of a diode-capacitor peak detector and bleeder resistor. It was all in firmware.

Is this a school assignment?

5. ### soderdaen Thread Starter New Member

Nov 21, 2015
16
1
Ah ok, reducing highvalue is a nice idea, I will try that.

It's for my bachelor thesis at the university. The main part is the hardware side, I did not know the programming part would be that hard. And programming is definately not my favourite subject..

Edit: Oh that helped me a lot, thanks for the advice. Now it's just in the falling part of the sine that makes bad values. But doing the routine for the bottom halfwave and waiting for the zero cross and then going to my upper_halfwave routine should do it i guess.

Last edited: Jan 21, 2016
6. ### NorthGuy Active Member

Jun 28, 2014
611
121
If you used a diode to rectify it, you have added a biss caused by the voltage drop across diode.

As for the math, I would suggest to do as follows, which is probably the easiest:

1. Read N values (e.g. 10) and calculate the highest of them as you read them. Set the highest value to the calculated number.

2. Read next N values and calculate the highest of them. While doing so, keep outputting the highest value calculated on step 1.

And so on.

If you have computing power, you can calculate RMS - square root of the sum of squared samples. That's the way AC is usually measured.

Code (C):
1.
2.   // code to calculate the highest value
3.
4.   int ret_val = 0;
5.   int count = 0;
6.   int cur_val = 0;
7.
8.
10.
11.    if (adc_val > cur_val) {
13.    }
14.
15.    if (++count == 10) {
16.      count = 0;
17.      ret_val = cur_val;
18.      cur_val = 0;
19.    }
20.
21.    return ret_val;
22.
23. }
24.

Last edited by a moderator: Jan 21, 2016
7. ### ErnieM AAC Fanatic!

Apr 24, 2011
7,443
1,628
Where does the "10" come from?

You have a pulsing wave with some period. How fast is your A2D sampling this wave? How long until 10 samples happen?

For your scheme to work you want to collect a lot of data across at least one period of time to insure you caught the peak value.

8. ### soderdaen Thread Starter New Member

Nov 21, 2015
16
1
The 10 is random.

Sampling rate is is Clock /1024. The ten samples are just for false values.
I managed to solve my problem by DickCappels advice. The part which made problem is then being solved in the main function waiting for the zero crossing.

The bias by the diode will later be considered.

I think thats interesting, I am going to look up how it works.

Thank you all for now

9. ### joeyd999 AAC Fanatic!

Jun 6, 2011
2,759
2,943
I do things like this the hard way...my code would actually simulate an analog peak detector using a digital filter. I'd program the decay time of the filter to whatever desired, perhaps dynamically based upon the computed period of the incoming waveform.

10. ### dannyf Well-Known Member

Sep 13, 2015
2,196
417
Because your code is designed that way. Maybe you should only increment the counter when the adc value is above a threshold value - when you consider the data to be valid.

Sounds like you are measuring AC, not pulsed DC.

11. ### dannyf Well-Known Member

Sep 13, 2015
2,196
417
Assuming low frequency AC, you should consider some form of "continuous adc":

1) start the adc if zero-crossing is detected;
2) continues to perform adc, and save the highest value until the next zero-crossing is detected.
3) return the highest value.

Your code has a uart procedure in there. Arduino's uart isn't interrupt driven and is very slow so you may have performed adc during different cycles.

12. ### dannyf Well-Known Member

Sep 13, 2015
2,196
417
I put this together quickly to see how I may do it.

It is a simple routine that detects the peak of an analog signal (0-5v). Once a minimum threadhold, ADC_MIN=200(1v@5v Vref), is reached, the routine starts to save the peak value (=4.5v = 920.7 -> 921 @ 5v Vref).

As you can see, it correctly detected the peak here.

I used adc to detect the beginning and ending threshold. A digital input will work as well, assuming sufficient signal swing.

File size:
50.9 KB
Views:
12
13. ### soderdaen Thread Starter New Member

Nov 21, 2015
16
1
It is pulsed DC. But I think the adc is not that exactly and measures some times a value which is not zero

Your second post is interesting, maybe I will try that next week when I have time again for that project.
Thank you everyone

Edit: I just see your third post. Looks good, but I think your sine wave does not have noise which is the real problem here. By the way: What programm is this? Can you simulate the code on the Pc and connecting your device virtually ?

14. ### ErnieM AAC Fanatic!

Apr 24, 2011
7,443
1,628
You don't state what device you are using but many devices are capable os "in circuit debugging" where you can set break point or even step your code line by line and see how your code works in the actual hardware.

I work with Microchip devices and their PICkit programmer (under \$50) can Aldo do debugging like this. It is quite a valuable tool to have.

One point to emphasize in Danny's work is his use of a min test to bypass the near zero values and only start testing values when they are in the area where the peak occurs. That is what the two while loops do at lines 52 and 5C.

15. ### soderdaen Thread Starter New Member

Nov 21, 2015
16
1
I am working on the ATmega 328p on Arduino Uno. I just kind of "debug" by usart giving out adc values and I also have a oscillocope here to measure high frequent pin changes.

16. ### soderdaen Thread Starter New Member

Nov 21, 2015
16
1
PUSH:

Does anyone know what programm dannyf used for the screenshot?

17. ### joeyd999 AAC Fanatic!

Jun 6, 2011
2,759
2,943
The "print screen" button?

soderdaen likes this.
18. ### shteii01 AAC Fanatic!

Feb 19, 2010
3,518
515
Print Screen key on the keyboard takes the shot. Then paste in whatever program you use for picture editing. I use IrFanView (free). New M\$ Paint works since they now allow to save in jpeg format. There is White Rabbit photoshop that you can find, that was pre release of Photoshop 5 or CS5 that was leaked.

Interesting feature of Print Screen is Alt+Print Screen, takes snap shot of the active window, not the whole desktop.

19. ### soderdaen Thread Starter New Member

Nov 21, 2015
16
1
Oh haha fail.
I meant the Programm IN the Screenshot of course ^^

joeyd999 likes this.
20. ### soderdaen Thread Starter New Member

Nov 21, 2015
16
1
So anybody ?

Sorry for spam, but I need the programm for today