Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Real time serial data acquisition

Status
Not open for further replies.

ambilys

New Member
Hi

I wish to take the samples from pic16f877a,4Mhz HS( if it is given a sine wave input) and plot the same.I am giving 230vp sine wave 50hz as input and transformed it into 5v range and level shifted it into positive voltages.

This is my code

Code:
                              // Loop variable


      float val,val1;//Declare the adcvalue stored variables
      char uart_rd[50],uart_rd1[50];

      void main()
      {
          TRISA=0XFF;//porta as input
      ADCON1 = 0x82; // AN0->AN4 selected as analog input
        ADCON0 = 0b11000001; // Configue analog mode

           UART1_Init(9600);               // Initialize UART module at 9600 bps


          while(1)
          {
          val=ADC_Read(0);
          val1=(val*325.0)/1023.0;
          FloatToStr(val1,uart_rd1);
             strncpy(uart_rd,uart_rd1,3);
             UART1_Write(val1);

             //UART1_Write(10);
            UART1_Write(13);
            delay_us(1);

       }
       }

I have checked the values in hyperterminal and see that the controller not even sample the peak voltage.I wish to have the samples correctly so that I can able to plot the waveform correctly.
 
Can't find anything else wrong with your code other than you are wasting time for unnecessary calculations and string manipulations. And your baudrate is really low.
Just send the raw ADC result through the uart if you need maximum speed.

int val;
char uart_rd[10];

while(1)
{
val=ADC_Read(0);
itoa(val,uart_rd, 10);
UART1_Write(uart_rd);
delay_us(1);
}
 
Last edited:
First of all, you got the formula wrong.

It is AC, so it'll go from -325V to +325V. You probably need to give it some margin, so that the range is actually -400V to +400V (or similar). For it to spread beween 0 and 5V you need to attenuate it 800/5 = 160 times (or so) and shift 2.5V. Let's suppose you did this correctly. After the attenuation and the shift, 0V corresponds to -400V, 2.5V to 0V and 5V to +400V. Or, in ADC readings 0 is -400V, 512 is 0V and 1023 is +400V. The correct formula to reflect this relationship would be:

V = 800*(val-512)/1023;

A magic of copy and paste.
 
How wrong you have to go that it matters?
 
How wrong you have to go that it matters?

You cannot improve the accuracy of the signal that you measure. So, if the accuracy is 1% (as if you used 1% resistors for a voltage divider, ignoring other errors), then you can only have 100 meaninful counts. Everything else is a noise. If you use 300-400 counts, your rounding error (0.3%) will not matter - the combined error will be sqrt(1^2 + 0.3^2) = 1.05%.

If you somehow got into a situation where every ADC count matters, you need a better ADC.
 
You cannot improve the accuracy of the signal that you measure.
You can improve the accuracy of your measurements. Add a little bit of noise and oversample.
 
Can't find anything else wrong with your code other than you are wasting time for unnecessary calculations and string manipulations. And your baudrate is really low.
Just send the raw ADC result through the uart if you need maximum speed.

int val;
char uart_rd[10];

while(1)
{
val=ADC_Read(0);
itoa(val,uart_rd, 10);
UART1_Write(uart_rd);
delay_us(1);
}
 
Can't find anything else wrong with your code other than you are wasting time for unnecessary calculations and string manipulations. And your baudrate is really low.
Just send the raw ADC result through the uart if you need maximum speed.

int val;
char uart_rd[10];

while(1)
{
val=ADC_Read(0);
itoa(val,uart_rd, 10);
UART1_Write(uart_rd);
delay_us(1);
}
itoa is an undeclared identifier in mikroc
 
You can improve the accuracy of your measurements. Add a little bit of noise and oversample.

Adding a noise will only increase the error.

Taking an average of multiple samples does decrease the error by sqrt(N). But it has nothing to do with single measurements. When you take an average, the resolution increases too. Say, you average 100 integers. The average will have 0.01 resolution. Note that resolution increases N times, while accuracy increases sqrt(N) times, which means that the gain in accuracy will be less than the gain in resolution. It is, therefore, no reason to get extra resoltion for individual samples.

It's not applicable to OP who wants to get the shape of the curve and therefore cannot oversample. The important thing is that he missed by a factor of two in his formula.
 
Adding a noise will only increase the error.

Taking an average of multiple samples does decrease the error by sqrt(N). But it has nothing to do with single measurements. When you take an average, the resolution increases too. Say, you average 100 integers. The average will have 0.01 resolution. Note that resolution increases N times, while accuracy increases sqrt(N) times, which means that the gain in accuracy will be less than the gain in resolution. It is, therefore, no reason to get extra resoltion for individual samples.

It's not applicable to OP who wants to get the shape of the curve and therefore cannot oversample. The important thing is that he missed by a factor of two in his formula.
factor of 2 means?
 
It's not applicable to OP who wants to get the shape of the curve..
He already knows the shape of the curve.. he just wants to plot it so he can admire it.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top