# Derive peak value from two points on a sinewave?

Discussion in 'Math' started by THE_RB, Nov 2, 2012.

1. ### THE_RB Thread Starter AAC Fanatic!

Feb 11, 2008
5,435
1,305
Hi, I'm doing a DSP application on quite limited microcontroller hardware, and need a fast crude process to find a sinewave peak value based on two points on the sinewave which are guaranteed to be 90 degrees apart.

The two points are already full-wave rectified, so there are no negative values. Both values are already in the range 0-127 (7bit binary).

Normally this is found as the "square root of the sum of the two squares", which obviously works fine but I need to do this fast with no squares or roots, hopefully just with some additions/subtractions, and binary mult/divide (left/right shifts on a micro).

I also prefer not to use a lookup table. The good news is that the final accuracy only needs to be +/- 3%.

As an example I am currently using this calc;
peak = biggest - dif/4
(dif = biggest-smallest, where biggest and smallest are the two values), and it gets pretty close;

Code ( (Unknown Language)):
1.
2. Big Small   RMS Mine
3. 0   100 71  75
4. 36  90  71  76
5. 71  71  71  71
6.
This gives a result within about 8% of the real RMS value, so it's almost accurate enough but leaves me with a problem of turning the RMS result into a peak result (ie *1.41).

If anyone has a fast simple way of getting a peak value within +/-3% or so it would be much appreciated!

2. ### nigelwright7557 Senior Member

May 10, 2008
480
69
To mpy by 1.41 mpy by 14 then divide by 10 using integers.

3. ### MrChips Moderator

Oct 2, 2009
12,228
3,282
No.

To multiply by 1.414, multiply by 362 and divide by 256 (i.e. use the upper byte).

If the multiplication has the potential to exceed 16 bits, then there are ways of dealing with this,

such as...

multiply by 106 and divide by 256, then add the original number.

(In your case, the number is 7 bits and hence the product will not exceed 16 bits).

Last edited: Nov 3, 2012
4. ### THE_RB Thread Starter AAC Fanatic!

Feb 11, 2008
5,435
1,305
Thanks guys, I can do simplified mucltiplications and divisions.

What I'm really after is some input from math guys if there is a simple way to do the calc to find the peak sine value based on the 2 points at 90 degrees apart on the sine wave.

It's not a big rush, i've been checking out the possibility of using a lookup table which can do the job but is not the method I would prefer. Maybe someone has some type of simple transfer function etc to do the job?

5. ### MrChips Moderator

Oct 2, 2009
12,228
3,282
Why not go the square root of the sum of the squares route?
I am sure we can come up with an efficient way to calculate the square root.
I once did it for logarithm.

6. ### THE_RB Thread Starter AAC Fanatic!

Feb 11, 2008
5,435
1,305
Because I'd like to do it in about 5 to 10 assembler cycles...

Something like the old 2D graphics trick for fast hypotenuse; h = a + (b/2) where you add half the smaller number to the larger number, instead of; 2 squares an additon and a square root.

I've checked my other code and can work with either a peak result or a RMS result, so I can work with;
0 + 100 -> 100 (result is the sine peak)
71 + 71 -> 100
or alternatively
0 + 100 -> 71 (result is the RMS)
71 + 71 -> 71

What I have so far (for example) is;
big + (small * 0.375)

Code ( (Unknown Language)):
1.
2. Small   Big PEAK    Mine
3. 0   100 100 100
4. 36  90  100 103
5. 71  71  100 98
6.
That gets me within about 3-4% of accurate, and is not too bad as *0.375 is *3/8, which is easy to do in binary as *3 then >> 3.

But I'd like it more accurate if possible.

7. ### Ron H AAC Fanatic!

Apr 14, 2005
7,050
655
I don't get it. Do you know the phase of the two samples? If not, how can you calculate the peak? Samples at 45° and 135° will be at the same level.

8. ### THE_RB Thread Starter AAC Fanatic!

Feb 11, 2008
5,435
1,305
Hi Ron, sorry I probably didn't explain well enough. The data corresponds to a sine. The two samples are always exactly 90 degrees apart in relation to the (known) sine frequency.

I needs a very fast simpel way to get the peak value from the height of the two samples (which are already "full wave rectified" so heights are all positive).

9. ### Ron H AAC Fanatic!

Apr 14, 2005
7,050
655
But what are the phases of the samples, relative to the sine?

10. ### MrChips Moderator

Oct 2, 2009
12,228
3,282
Does your MCU have hardware multiply or divide?

Oct 2, 2009
12,228
3,282
12. ### MrChips Moderator

Oct 2, 2009
12,228
3,282
If you can do a multiply to find the square, try

if x > y

y1 = (y * y) / 256

y2 = y1 / 2

r = x + y1 + y2

13. ### THE_RB Thread Starter AAC Fanatic!

Feb 11, 2008
5,435
1,305
That is unknown but irrelevant, there is always 90 degrees between the two samples. It's irrelevant because the full wave rectification gives two identical 180 degree half sines, and then each of those is two identical quadrants (mirrored). So only two points at 90 degrees apart are needed to calc the sine peak.

To MrChips; thanks for the CORDIC reference, it was a good read but even though using relatively simple code it's similar to successive approximation which can require numerous cycles, so it's very slow compared to my present solution which is only one iteration of a few assember instructions.

Interesting, and thank you. I'll have a play with that and see how it goes for time and accuracy.

14. ### MrChips Moderator

Oct 2, 2009
12,228
3,282
Sorry, my proposed solution only works at a given value of r = 100.
I will have to rethink this.

15. ### Ron H AAC Fanatic!

Apr 14, 2005
7,050
655
Yeah, I finally figured that out on my own. Sometimes I'm a little dense.

16. ### Tesla23 Active Member

May 10, 2009
318
67
The approach you are trying is best shown graphically:

where you are doing a linear approximation, breaking at x=y.

A slightly CORDIC inspired approximation is:
0 <= y < x/2 : amp = x + 0.236*y
x/2 < y < x : amp = 1.414*x + 1.019*y - 0.7208

This gives an error between 0 and +2.7% (it's always positive so there is further tweaking you can do). You may get something reasonable by playing around with binary inspired approximations to this.

File size:
19 KB
Views:
56
17. ### MrChips Moderator

Oct 2, 2009
12,228
3,282
I have fixed the algorithm but now it requires one multiply and one divide and some shifts:

if x > y

y1 = y * y / x

y2 = y1 / 2

y3 = y2 / 8

r = x + y2 - y3

Last edited: Nov 10, 2012
18. ### THE_RB Thread Starter AAC Fanatic!

Feb 11, 2008
5,435
1,305
Thanks Tesla23 that has given me something to think about. At first glance I'm not favoring splitting the calc into 1 of 2 processes, it already has the time cost of the first split if(x>y) and then the second split and dual multiplications is going to make it slow I think...

Thanks MrChips. The new algo is not as bad as it looks time wise;

if x > y
y1 = y * y / x // this is still a bit unpleasant
y2 = y1 / 2 // fast, can be >>1
y3 = y2 / 8 // fast, can be another >>3
r = x + y2 - y3 // fast, can be done on the fly

I have not had time to check it out just yet but should get some time over the next few days.

19. ### Tesla23 Active Member

May 10, 2009
318
67
A slight refinement on Mr Chips algorithm:

for y < x

$amp = (1 - 2^{-5} - 2^{-6})x + (2^{-1} - 2^{-4})y$

or

$amp = 0.953*x + 0.4375*y$

gives max error < 5%