Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Finding the amplitude of sine wave in CCS C (program)

Status
Not open for further replies.

engineerelectrical

Newbie level 6
Joined
Dec 22, 2016
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
105
I am using a PIC18F6722 microcontroller. I have hooked up a function generator to pin A1 to get the various values for the sinewave. I want to write code to find the amplitude of the sine wave. How should I go about doing this? So, far this is my code:


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <18F6722.h> 
#device ICD = TRUE 
#fuses HS, NOLVP, NOWDT 
#use delay (clock=20000000) 
#USE rs232 (baud=9600, xmit = PIN_C6, rcv=PIN_C7) 
 
#include<utility.c>
#include<math.h>
 
void main()
{
    int reading, i;
    int8 imin = 255;
    int8 imax = 0;
    
    float array[10];
    float Volts;
    float a = 5.0, b = 255.0;
    int ctr = 0;
 
   setup_adc_ports(AN0_TO_AN1);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(1);
 
   while(TRUE)
   {
       for(i=0; i<=9; i++)
       {
           reading = read_adc();
           Volts = reading*(a/b);
           array[i] = Volts;
           printf("\r\n%f", array[i]);
       }
        
       if(ctr==9) break;
       ctr++;
   }
   
   for(i=0; i<=9; i++)
   {
       if(array[i]<imin)   imin=array[i];
       if(array[i]>imax)  imax=array[i];
    }
}



I am new to programming so any help would be much appreciated! Thanks in advance.
 
Last edited by a moderator:

Hi,

* find max level
* find min level
* if min level = 0 then error
* if max level = 1023 then error
* amplitude = (max_level - min_level) / 2

Klaus
 

I don't think that float type is suitable for your purpose. U have 10 bit adc, so use unsigned short type than.
 

I don't think that float type is suitable for your purpose. U have 10 bit adc, so use unsigned short type than.

Furthermore, the operation "x*(a/b)" which has 1/41 as result of the a/b division(=5/255), could be replaced by "(x*25)>>10", which would give less that 0,1% of error on final result. Note that x/41 is almost the same as (x*24,975...)/1024. In shorts, depending on your accuracy requirements, you can even replace the intrinsic C division operation performed by float casting, with tricky and fastest operations.
 

You should also think about the ADC sampling rate and if it's suitable to get a representative measurement of the sine magnitude.

Do you understand that the sampling rate of your code is mainly defined by float calculations and UART output?
 

Hi,

* find max level
* find min level
* if min level = 0 then error
* if max level = 1023 then error
* amplitude = (max_level - min_level) / 2

Klaus

The code I used in the second for loop finds the min and the max level correct?
 

The code I used in the second for loop finds the min and the max level correct?

For learning purpose, it's ok; What we're attempting to tell you is that the code could converge to final result faster by making few changes.
 

For learning purpose, it's ok; What we're attempting to tell you is that the code could converge to final result faster by making few changes.

Thanks! I will make the changes mentioned to do just that. Also, if I were to change the value of i to, lets say, 49, then that means I would have 50 various values to look at to find the amplitude correct? Instead of having just 10 values.
 

lets say, 49, then that means I would have 50 various values to look at to find the amplitude correct? Instead of having just 10 values
Considering that you are perhaps using AD with 8 bits resolution ( that mean, 256 possible values ), performing assynchronous readings, you surelly should take much more samples in order to make a reliable measurement. Anyway, from the statistical point of view, even if you do not reach all possible values, the more samples, the more accurate the result becomes.
 

Considering that you are perhaps using AD with 8 bits resolution ( that mean, 256 possible values ), performing assynchronous readings, you surelly should take much more samples in order to make a reliable measurement. Anyway, from the statistical point of view, even if you do not reach all possible values, the more samples, the more accurate the result becomes.

Thank you! Also, if I were to find the frequency for my sine wave how would I go about coding it? Would I need to use timers and/or interrupts?
 

if I were to find the frequency for my sine wave how would I go about coding it?
As mentioned before in a different context of this thread, the timming for sending each sample with the above code is not deterministically defined, so you should use timer to provide precise interruptions on which each sample should be aqcuired. I'm particularly unaware if exists another way than FFT variants to take the fundamental frequency of a signal without having a reasonable and precise amount of samples per cycle.
 

As mentioned before in a different context of this thread, the timming for sending each sample with the above code is not deterministically defined, so you should use timer to provide precise interruptions on which each sample should be aqcuired. I'm particularly unaware if exists another way than FFT variants to take the fundamental frequency of a signal without having a reasonable and precise amount of samples per cycle.


I was looking at FFT but would the pic18f6722 be able to handle FFT? I'm not sure if it would but if it can then I will implement it.
 

Hi,

I'd say every processor can handle an FFT.
A smaller processor takes more time.

But it doesn't depend only on the processor.
* coding
* data format
* FFT depth
...have big influence on processing speed.

*****
Back to the "amplitude" task.
The min/max solution is one of the worst regarding precision. It takes only the two extreme values out of a number of samples.
The FFT is one of the best, because it takes all samples into calculation.

I recommend to go step by step.
* sampling with a fixed frequency
* filters
* averaging
* RMS
* FFT

****
Finding frequency
A simple an very precise solution is to use a comparator combined with the capture function of the microcontroller (instead of ADC).

Klaus
 

Highest value of a sine wave

This might be a really silly question here but I can't seem to figure it out. So I have created an array which stores 50 values of a sine wave generated by a function generator. I want to find the location of the max value in this array. I already did that but sometimes the max values are in various location in the array and my program only gives me the very first location the max value is encountered.

The code below only shows the part of the code where the location of the max and min values are printed.

Code:
float array[50];
int I;
int location1 = 1;
long location2 = 1;
float imin = 255;
float imax = 0;

for(I=0; I<=49; I++)
{
     if(array[I]<imin)
     {
         imin = array[I];
         location1 = I+1;
      }

      if(array[I]>imax)
      {
          imax = array[I];
          location2 = I+1;
       }
}

How do I print out the highest location the max value is encountered? For example: if 4.5 was the max and it appeared in locations 6 and 25, how do I make sure my program prints out 25 instead of 6. Thanks!
 

Re: Highest value of a sine wave

Isn't that logically:

for a minimum
Code:
array[I] <= imin

for a maximum
Code:
array[I] >= imax

If the maximum or minimum is the same as a previous value the location gets updated along with the min/max values.
 

Re: Highest value of a sine wave

Isn't that logically:

for a minimum
Code:
array[I] <= imin

for a maximum
Code:
array[I] >= imax

If the maximum or minimum is the same as a previous value the location gets updated along with the min/max values.

Thanks! I was overthinking this way more than I should've.
 

As mentioned before in a different context of this thread, the timming for sending each sample with the above code is not deterministically defined, so you should use timer to provide precise interruptions on which each sample should be aqcuired. I'm particularly unaware if exists another way than FFT variants to take the fundamental frequency of a signal without having a reasonable and precise amount of samples per cycle.

Hey,

So I acquired various values for the amplitude of the sine wave and stored it in an array. Some of the values are listed below:

4.5
4.43
4.33
4.17
4
3.78
3.54
3.27
3
2.7
2.39
2.07
1.76
1.47
1.17
0.92
0.68
0.47
0.29
0.15
0.05
0
0
0
0.07
0.21
0.35
0.52
0.76
1
1.27
1.56
1.86
2.17
2.49
2.8
3.07
3.39
3.62
3.88
4.07
4.23
4.37
4.47
4.5
4.54
4.49
4.41
4.29
4.15
3.98
3.74
3.5
3.21
2.94
2.62
2.33
2.01
1.7
1.41
1.13
0.86
0.62
0.43
0.25
0.13
0.03
0
0
0.01
0.09
0.23


Given this data, how would I go about finding the frequency? I tried finding the max and min value locations, found their difference and then multiplied by the delay but it does not seem to give me the correct value for the frequency. Thanks in advance!
 

it does not seem to give me the correct value for the frequency

You did not implement on this code any kind of interrupt driven timing to give you a precise and reliable sample rate.
 

Frequency

You did not implement on this code any kind of interrupt driven timing to give you a precise and reliable sample rate.

hmmm how should I implement an interrupt driven timing? Because for some periods the max value is different. For example: sometimes the max value is 4.5 whereas in other times it is 4.52 so I'm not sure how to account for that.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top