• AVR Freaks

Helpful ReplyHot!PIC16F : ADC Stable Reading How to ?

Page: 12 > Showing page 1 of 2
Author
karan123
Super Member
  • Total Posts : 970
  • Reward points : 0
  • Joined: 2009/02/02 11:11:21
  • Location: 0
  • Status: offline
2019/11/29 22:31:35 (permalink)
0

PIC16F : ADC Stable Reading How to ?

Hi
 
I am working on PIC16F876A MCU Only Single Channel 10-Bit ADC (AN0) is used.
My single single reading are varying . So I am trying with taking average as below.
 
But Reading are still varying after taking  average (in variable avg1).
 
PIC16F <- LF356N <- Photo Diode .
 

void ADCInit()
{
// ADCON1 = 0x0E ; // Left Justified (Not Used)
ADCON1 = 0x8E ; // Right Justified + AN0 is Analog(And All other Digital)

CHS2 = 0 ; // Select AN0
CHS1 = 0 ; // Select AN0
CHS0 = 0 ; // Select AN0
ADCS1 = 0 ; // Fosc = 32MHz
ADCS0 = 1 ;
ADON = 1 ; // ADC Module ON
}
int ReadADC(void)
{
GO = 1 ; // Start Conversion
while(GO == 1 ) ; // Wait Untill Complete
return (((unsigned int)ADRESH)<<8)|(ADRESL);
}
for(loop=0 ; loop < 200;loop++)
{
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
MeasuredReadingValue1 += ReadADC() ;
}
Avg1 = MeasuredReadingValue1/200 ;
printf("Avg1 = %f \r\n",Avg1);    
MeasuredReadingValue1 = 0 ; // Reset for Next Round



 
How I can use Software Filter or other method for stable reading ..
 
--
Karan
#1
ric
Super Member
  • Total Posts : 27979
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/11/29 22:57:22 (permalink)
+1 (1)
What about your hardware?
You are using mode 0b1110, so it's using VDD as Vref+, so any noise on Vdd is going to add noise to your signal.
Do you have a good low ESR bypass capacitor connected with very short tracks to pins 19 + 20 (Vss + Vdd), as well as a short track connecting pins 8 + 19 ?
Do you have a low pass filter on the ADC input pin?
(e.g. a 1k resistor and 100n capacitor can make a simple RC low pass filter.)
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#2
Mysil
Super Member
  • Total Posts : 3677
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/11/30 07:21:20 (permalink) ☄ Helpfulby TS9 2019/12/09 00:09:25
+2 (2)
Hi,
You haven't  actually stated what system clock frequency the device is running.
There are 3 bits that control how fast the ADC conversion clock will work, in two different registers:
ADCS2, ADCS1 and  ADCS0
The ADCS2 bit you have cleared to 0 in ADCON1 above
Then you have:  ADCS1 = 0 ;  ADCS0 = 1;  This should give FADC = FOSC / 8;
And should probably be OK, if  microcontroller is running from internal oscillator at 8 MHz.
 
16 NOPs between measurements would be 8 MHz / 4 / 16 = 125 kHz
or 8 microseconds charging time for the ADC sampling capacitor.
 
Code snippet  do not really show what type the averaging accumulator  MeasuredReadingValue1 is declared.
16 bit integer will overflow when 200 10 bit values are added together, depending on actual measurement values.
  24 bit unsigned integer will be needed, or you may use 32 bit integer.
 
You are measuring a photodiode,  what is the photodiode seeing?
Is the photodiode seeing a flickering lamp? Is there any mains powered  lights influencing the photodiode?
You may try to Time the measurements, such that time for  measurements
is the same as one or more whole periods of main AC frequency
Example: 50 Hz mains frequency is 20 milliseconds period time. 
200 measurements in 20 ms,   is  100 microseconds.
You may try to use a timer set for a period of 100 microseconds,
and start a ADC conversion when the timer turn around.
Example: Timer 2 with Prescaler   1:4  and Period register 49,
         Or: Timer 2 with Prescaler   1:1 Period register 99  and Postscaler   1:2.
Watch the Interrupt Flag   TMR2IF,  no need to enable interrupts, unless you want to. 
 
Note: I have NO confirmation of what Oscillator frequency your device is actually running.
That archaic device do not have an internal FRC oscillator available for use as system clock.
External  RC circuit may run at any arbitrary frequency, or do you have a Crystal tuned at what frequency? 
Redo all calculations and assumptions above with actual system frequency.
 
    Mysil
#3
pcbbc
Super Member
  • Total Posts : 1703
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/01 21:19:51 (permalink)
+1 (1)
Also general style point: using a power of 2 for the number of samples being averaged is recommended on 8-bit devices.
So 64, 128, 256 etc.
Then the expensive divide operation can be converted into a simple shift.
#4
PStechPaul
Super Member
  • Total Posts : 2813
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/02 02:02:15 (permalink) ☄ Helpfulby Jim Nickerson 2019/12/02 08:19:56
+2 (2)
Also, you don't have to divide by the number of samples for an average. For instance, if you are measuring 10-15 VDC, you might use a 4:1 divider to get the voltage 2.50-3.75 VDC and use a 5 VDC reference, where the 10 bit ADC will read 512-768 counts. If you take a total of 20 samples you will have integer values of 10,240 to 15,360. You can adjust the voltage divider slightly and get 10,000 to 15,000, and display the results to three decimal places.
 
To help determine the cause of the unsteady readings, you could read the maximum and minimum values over the sample period, to see just how much variation there actually is. Also use a scope on the analog input as well as on the reference (or Vdd) to see if there is significant noise.

 
#5
TS9
Super Member
  • Total Posts : 879
  • Reward points : 0
  • Joined: 2010/05/07 10:52:22
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/08 06:28:31 (permalink)
0
<Edited>Where did you get the reading?
post edited by TS9 - 2019/12/08 07:06:20
#6
karan123
Super Member
  • Total Posts : 970
  • Reward points : 0
  • Joined: 2009/02/02 11:11:21
  • Location: 0
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/08 06:53:13 (permalink)
0
Hi,

Thanks All for yours reply n Sorry for Delay from my side.
@ric
Yes,I am using VDD as Vref , there are .1uF Caps and Power Supplies Pins on Both side.

@Mysil
I am trying to make Colorimeter with PIC16F876A with is based on Lambert's law.
https://en.wikipedia.org/...olorimeter_(chemistry)
https://en.wikipedia.org/...er%E2%80%93Lambert_law


So , It is not releated to AC Measurements.
I am using 4MHz External Crystal Oscillator with 33pF Capacitor as clock frequency .
Please Find Detail Snipshort with variable type information.

void ADCInit()
{
// ADCON1 = 0x0E ; // Left Justified (Not Used)
ADCON1 = 0x8E ; // Right Justified + AN0 is Analog(And All other Digital)

CHS2 = 0 ; // Select AN0
CHS1 = 0 ; // Select AN0
CHS0 = 0 ; // Select AN0
ADCS1 = 0 ; // Fosc/32MHz
ADCS0 = 1 ;
ADON = 1 ; // ADC Module ON
}
int ReadADC(void)
{
GO = 1 ; // Start Conversion
while(GO == 1 ) ; // Wait Untill Complete
return (((unsigned int)ADRESH)<<8)|(ADRESL);
}
char array[10] ;
void main(void)
{
long MeasuredReadingValue1 = 0;
long MeasuredReadingValue2 = 0;
int loop = 0,Counter = 0 , Flag = 0 ;;
double FinalResult = 0,AfterDivide = 0;
double Avg1 = 0,Avg2 = 0 ;

System_INIT();
ADCInit() ;
TimerInit();
WaitSystemSwitchPressed();
InitSoftUART();
printf("Test UART At Baud Rate 1200") ;
while(1)
{
if( START_SW == 0) // If Switched is Pressed
{
__delay_ms(50);
if( START_SW == 0)
{
// sprintf(array,"%.2f \n",0.00);
// ResultToSegment(array);
Counter = 1 ;
Flag = 0 ;
}
}
if( Counter == 1)
{
if(Flag == 0) // Do this first time only once switched pressed
{
MeasuredReadingValue1 = 0 ; // Reset for Next Round
for(loop=0 ; loop < 256;loop++)
{
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
MeasuredReadingValue1 += ReadADC() ;
}
Avg1 = MeasuredReadingValue1/256 ;
Flag = 1 ;
}
MeasuredReadingValue2 = 0 ;
for(loop=0 ; loop < 256;loop++)
{
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
MeasuredReadingValue2 += ReadADC() ;
}
Avg2 = MeasuredReadingValue2/256 ;
AfterDivide = Avg1/Avg2 ;
FinalResult = log10(AfterDivide) ;
printf("\r\nAvg1 = %.2f \r\n",Avg1);
printf(" Avg2 = %.2f \r\n",Avg2);
printf("FinalResult = %.2f \r\n",FinalResult);
sprintf(array,"%.2f",FinalResult);
ResultToSegment(array);
}
}
while(1);
}

@pcbbc
Thanks ... But reading have still little fluctuations

@PSteachPaul
Thanks.. I have check waveform on CRO . But waveform not looks as fine as pure DC.

Now , My problem is that .. I am not getting same reading for same sample
which deteriorate whole result after calculations .

Hope Now I clear to all . What is the way to sort out this problem .
--
Thanks
Karan
post edited by karan123 - 2019/12/08 06:59:11

Attached Image(s)

#7
hudejun
Electrical engineer
  • Total Posts : 15
  • Reward points : 0
  • Joined: 2019/12/05 08:48:06
  • Location: 0
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/08 07:10:53 (permalink)
+1 (1)
All signals are varying continue due to various reasons.
Same sample and same reading....
It is almost impossible with PCB noise and power source...
Please make sure input sample is stable.
Also, please try to use OP-AMP ref circuit instead of using VDD.(Vref+ issue)
 And, Hardware filter will makes best results.(Active Low pass filter)
 
post edited by hudejun - 2019/12/08 07:12:52
#8
karan123
Super Member
  • Total Posts : 970
  • Reward points : 0
  • Joined: 2009/02/02 11:11:21
  • Location: 0
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/08 07:21:30 (permalink)
0
Thanks...

I am using LF356N Opamp before photodiode
and Input samples are very much stable...

Is there any other suggestion..?
In programming

--
Karan
#9
Mysil
Super Member
  • Total Posts : 3677
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/08 08:20:32 (permalink) ☄ Helpfulby TS9 2019/12/09 00:09:01
+1 (1)
Hi,
There are a lot of tricks related to precision ADC measurements.
Your original question indicate that you are picking up noise somewhere,
and reply in message#7 indicate that you are still picking up noise.
 
In message above, am not suggesting that you are doing AC measurements.
I am suspecting that you may be picking up AC mains frequency noise,
and suggesting a way to compensate for some of that.
 
Many of the tricks about stable ADC readings, are similar to avoiding noise in Audio amplifier circuits:
Grounding, shielding, regulating and filtering power supplies, avoiding ground loops, 
keeping power circuits and weak signals away from each other, and more...
If you know how to keep mains hum away from Audio signals,
all the same precautions are relevant when doing precision ADC measurements.
 
Twisted pair wiring, or shielded wiring for low level signals, is one of the precautions that may help.
Also, keeping Analog ground, and Digita ground separate, and connected in only one place,
e.g. in the ground plane  on the underside of a 2 layer circuit board, underneath the ADC corner of the microcontroller.
 
One particular trick when doing ADC measurements with a microcontroller,
is to make the microcontroller go to sleep while ADC is working:
Place a Sleep instruction immediately after starting ADC conversion,
and let ADC Interrupt wake up the microcontroller when conversion is completed.
 
In the case of a colorimeter, power to the light source illuminating the solution,
need to be regulated and filtered to the same quality as reference voltage for the ADC converter.
 
    Mysil
#10
btbass
Super Member
  • Total Posts : 362
  • Reward points : 0
  • Joined: 2004/12/10 13:50:32
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/08 23:58:47 (permalink) ☄ Helpfulby TS9 2019/12/09 00:09:05
0
I don't know if this will help but is useful to know.
It is possible to implement a simple low pass digital filter on the A/D reading.
The filter simulates a single pole filter that is normally realised in hardware with a series resistor and a shunt cap to ground.
The sampling frequency simulates the series resistor and the number of samples constant, simulates the shunt cap.
You define a global variable to hold the result.
The read A/D filter function must be called at regular intervals, (normally, timer interrupt driven).
The time constant of the filter is the number of samples multiplied by the reading frequency.
For example, if the read A/D function is called every 25mS and the sample size is 4,
the time constant of the filter is (4 * 25) = 100mS.
Watch out for accumulator overflow with large sample sizes.
As the A/D reading is being constantly updated in the background, the result is always available for you to use in your code.
 

/*--- Global variable ----*/

uint16_t input_volts; /* This is the filtered result */

/*--- Low pass filter (This function called from Timer Interrupt) ---*/

void read_input_volts(void)
  {
  static uint16_t LP_acc = 0U; /* Low pass filter accumulator */
  
  input_volts = LP_acc / 4U; /* Divide by sample size 4, this is the filtered result. */
  
  LP_acc += read_ad(); /* Call the A/D read function and add result to accumulator */

  LP_acc -= input_volts; /* Subtract filtered value from accumulator */
  }

 
#11
PStechPaul
Super Member
  • Total Posts : 2813
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/09 02:35:08 (permalink) ☄ Helpfulby karan123 2019/12/09 09:25:45
0

You are taking 200 readings and then dividing by 200, so the ADC value you are reading is 48 counts +/- 1 digit, which is pretty much the limit for any ADC. Try dividing by 20, and display the readings as three digits. You might get readings like 475, 480, 485, 490, which will better show the variations of the readings. Or, you could perform floating point division to get a result with an arbitrary number of significant digits to display.
 
But it would bed much better to use an op-amp to provide a voltage that utilizes more of the ADC's range of 10 bits, or 0-1023 counts. A reading of about 48 counts is only about 5% of maximum value. Another way to get better precision would be to use a precision 1.024 volt reference, which would give readings of about 235 counts, also +/- 1 digit. So you may get 234, 235, or 236, but dividing by 5 would be 46.8, 47.0, and 47.2.

 
#12
Mysil
Super Member
  • Total Posts : 3677
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/09 06:38:03 (permalink) ☄ Helpfulby karan123 2019/12/09 09:26:09
+1 (1)
Hi,
I agree with PStechPaul that displaying the results after averaging, with more digits.
would be helpful in analyzing and understanding the noise present.
While + and - 1 digit is the theoretical limit of resolution for each single sample from a ADC conversion,
this isn't true for the averaged result.
The Averaged result will have better resolution than 1 LSB of the converter.
so displaying the result as Accumulator value divided by 20, is an excellent suggestion.
It may even be used in the user's calculation of final results.
 
This is actually the same technique that is used  in high resolution 'Sigma/Delta' AD Converters
used in digital multimeters and other high resolution A/D converters, with 14 bit, 16 bit, 18 bit,
or even higher resolution.
For this to work, it is assumed that there is a little high frequency noise in the signal,
coresponding to about +/- 1 LSB of the AD converter,
and with a frequency higher than the sampling frequency of the ADC.
Some even apply dithering, that is adding a little high frequency noise to  the signal to be measured.
 
However, neither Averaging  nor Low Pass filter, in hardware or software, or high resolution ADC,
will help if there is Low frequency noise in the input signal,
that is if the noise have frequency lower than the period of averaging calculation. 
 
In fact, in results displayed in message #7 and #12,
the variations come quite regularly:
47, 47, 48, 48, 49, 49, 49, 48, 47, 48, 48, 47, 47, 48, 49, 49
 
With one more decimal digit in printing of averaged values, as Paul suggest,
I suspect that it may be possible to plot a quite recognizable sine wave like curve.
I am not sure if the interval between printing values, is constant, or not.
 
Another comment:
What 'btbass' is suggesting in message #11 is another way of organizing calculation average value,
sometimes called a moving average or running average. See Wikipedia.
But it is average calculation anyway, with results similar to what the original poster is already doing.
Such a moving average is a way of organizing the calculation such that,
a updated average result value is available for each measurement value inserted.
 
It does however require a division to be performed for each measurement value added,
instead of one division at the end of a batch of measurements, as the OP. have been doing all the time.
The effort of doing divisions may be reduced, by using number of samples that is a power of 2.
e.g. 4 or 8 or 16 or 32 or 64 ... or 256 ... or 1024, ... , as suggested by pcbbc in message #4 above.
The compiler may, or may not recognice these numbers, and replace the division with shift operations.
Or it may be programmed with shift operator in the code.
Averaging with a number of samples = 256, may be made efficient by picking away a whole byte, instead of doing a long division.
It will however Not remove low frequency noise.
 
    Mysil
 
post edited by Mysil - 2019/12/09 06:49:54
#13
oliverb
Super Member
  • Total Posts : 285
  • Reward points : 0
  • Joined: 2009/02/16 13:12:38
  • Location: 0
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/09 08:55:40 (permalink)
0
Do you have a way to measure the signal quality of the signal going into the PIC? Oscilloscope for preference.
Have you tested with a known clean voltage, e.g. a low value pot or a battery?
Using Vdd as Vref isn't ideal but should be workable to at least 10 bits.
Do you have anything else going on that could disrupt the measurement.
Better question is what else IS going on while the measurement is made.
 
#14
karan123
Super Member
  • Total Posts : 970
  • Reward points : 0
  • Joined: 2009/02/02 11:11:21
  • Location: 0
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/09 09:31:36 (permalink)
0
Hi,
 
Thanks Mysil and  PStechPaul 
I have modified code divided by 20 as per suggestion attached result .

 
char array[10] ;
long MeasuredReadingValue = 0;
int outer = 0 ,loop = 0,Counter = 0 , Flag = 0 ;;
double FinalResult = 0,AfterDivide = 0;
double Avg1 = 0,Avg2 = 0 ;
void ADCMeasureAverage(unsigned char SampleNumber) ;
void main(void)
{
 

System_INIT();
ADCInit() ;
TimerInit();
WaitSystemSwitchPressed();
InitSoftUART();
printf("Test UART At Baud Rate 1200") ;
while(1)
{ if( START_SW == 0) // If Switched is Pressed
{
__delay_ms(50);
if( START_SW == 0)
{
sprintf(array,"%.2f \n",0.00);
ResultToSegment(array);
Counter = 1 ;
Flag = 0 ;
}
}
if(Flag == 0)
{
Avg1 = 0 ; // Reset For Next Round
ADCMeasureAverage(0); // Take First Reading
Flag = 1 ;
} // End of If Lopp
Avg2 =0 ; // Reset For Next Round
ADCMeasureAverage(1); // Take Second Reading
AfterDivide = Avg1/Avg2 ;
FinalResult = log10(AfterDivide) ;
if(Counter ==1)
{
printf("\r\nAvg1 = %.2f \r\n",Avg1);
printf(" Avg2 = %.2f \r\n",Avg2);
printf("FinalResult = %.2f \r\n",FinalResult);
sprintf(array,"%.2f",FinalResult);
ResultToSegment(array);
}

}
while(1);
}
void ADCMeasureAverage(unsigned char SampleNumber)
{

MeasuredReadingValue = 0 ; // Reset for Next Round
for(loop=0 ; loop < 256;loop++)
{
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
NOP() ; NOP() ; NOP() ; NOP() ;
if(SampleNumber == 0)
MeasuredReadingValue += ReadADC() ;
else
MeasuredReadingValue += ReadADC() ;
}
if(SampleNumber == 0)
Avg1 += MeasuredReadingValue/20 ;    // 256
else
Avg2 += MeasuredReadingValue/20 ;    // 256
}
 

 
Please see and advice ..
--
Karan
 
post edited by karan123 - 2019/12/09 09:38:24

Attached Image(s)

#15
acharnley
Super Member
  • Total Posts : 573
  • Reward points : 0
  • Joined: 2016/05/01 06:51:28
  • Location: 0
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/09 16:20:02 (permalink)
0
Assuming your chip has a FVR you have a fairly accurate 1.024v source built into the chip so there's really no need to use VDD and the noise which comes with it.

Another trick recommended by Microchip for accuracy is if your CPU doesn't have to be active is to use interrupts and send the CPU to sleep (less noise again). [Update, beaten to it by Mysil]
post edited by acharnley - 2019/12/09 16:21:30
#16
Mysil
Super Member
  • Total Posts : 3677
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/09 19:01:38 (permalink)
0
Hi  acharnley,
Why do you assume that there is FVR on the chip OP is using?
It is specified in message #1 what device is beeing used,
and the datasheet is available on the device webpage.
 
    Mysil
#17
Mysil
Super Member
  • Total Posts : 3677
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/09 19:26:29 (permalink)
0
Hi, karan123
Print in message #15, show only 2 measurements in sequence, before there is a lot of time used for print and floating point calculations. This make it difficult to see if there is any pattern to the variations observed.
I have done some experiments with a variation of program from message #7,
to measure and store several measurements in series, into a Intermediate array,
and then print afterwards.
 
Program have been run on a PIC16F886, which is as close as I have, similar to the device you are using.
The board is sitting on the keyboard of my laptop, and signal input is from the analog Pot in the same board.
This is somewhat advantaegous to the ADC, as some variations in supply voltage may cancel out.
 
Attached are a couple of dump files from Watch window in debugger.
 
ADC Channel 0, is from Pot on the same board, routed half-way around the board, but the board is a 2-layer board with groundplane on the underside all the way underneath the trace.
 
ADC Channel 2, are measurements from ADC channel 2 connected with a generous wire loop in the air,
from input pin for channel0, to input pin for channel 2.
 
The Potentiometer is set for a voltage of about 0.5 V
Signal is sampled 256 times, and accumulated into the 32 bit integer accumulator.
The sum is then shifted 4 bits to the right, to make sure the value can fit in a 16 bit integer variable,
and stored in a Intermediate array with 20 places,
and printed when all 20 measurements are done.
 
Result value for channel 0:  0x690,  decimal 1680,
correspond to:  1680 * 5000 mV  / 1024 / 16 = 512.7 mV.
 
The .jpg image is a spectrum from a oscilloscope I have,
showing noise in the signal from the wire loop from ADC0 input to ADC channel 2 input pin.
 
    Mysil
post edited by Mysil - 2019/12/09 20:19:05

Attached Image(s)

#18
LdB_ECM
Super Member
  • Total Posts : 404
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/09 19:30:09 (permalink)
0
I would suggest you carefully read section 11.1 from the MCU datasheet, as PStecthPaul noted above there is a pattern to your problem.
#19
karan123
Super Member
  • Total Posts : 970
  • Reward points : 0
  • Joined: 2009/02/02 11:11:21
  • Location: 0
  • Status: offline
Re: PIC16F : ADC Stable Reading How to ? 2019/12/09 20:18:37 (permalink)
0
Hi Mysil ,
 
Thanks for attachments and waveform. 
I have attached latest reading #18. and created a function createdADCMeasureAverage(unsigned char SampleNumber).

char array[10] ;
long MeasuredReadingValue = 0;
long AvgM = 0;
int outer = 0 ,loop = 0,Counter = 0 , Flag = 0 ;;
double FinalResult = 0,AfterDivide = 0;
double Avg1 = 0,Avg2 = 0 ;
unsigned short IntermediateValue1[20];
void ADCMeasureAverage(unsigned char SampleNumber) ;
void main(void)
{
System_INIT();
ADCInit() ;
TimerInit();
WaitSystemSwitchPressed();
InitSoftUART();
printf("T0") ;
while(1)
{
// printf("C = %d \r\n",Counter);
if( START_SW == 0) // If Switched is Pressed
{
__delay_ms(50);
if( START_SW == 0)
{
sprintf(array,"%.2f \n",0.00);
ResultToSegment(array);
Counter = 1 ;
Flag = 0 ;
}
while(START_SW == 1) ;
__delay_ms(50) ;
}
if(Flag == 0)
{
Avg1 = 0;
ADCMeasureAverage(0); // Take First Reading
Flag = 1 ;
}
Avg2 = 0;
ADCMeasureAverage(1); // Take Second Reading
printf("\r\nAvg1 = %.2f \r\n",Avg1);
printf("Avg2 = %.2f \r\n",Avg2);
AfterDivide = Avg1/Avg2 ;
FinalResult = log10(AfterDivide) ;
if(Counter ==1)
{
// printf("\r\nAvg1 Final = %.2f \r\n",Avg1);
sprintf(array,"%.2f",FinalResult);
ResultToSegment(array);
}
printf("\r\nAvg1 = %.2f \r\n",Avg1);
printf("Avg2 = %.2f \r\n",Avg2);
// printf("FinalResult = %.2f \r\n",FinalResult);
}
}
while(1);
}
void ADCMeasureAverage(unsigned char SampleNumber)
{
for (Flag = 0; Flag < 20; Flag += 1)
{
MeasuredReadingValue = 0; // Reset for Next Round
for (loop = 0; loop < 256; loop++)
{
NOP(); NOP(); NOP(); NOP();
NOP(); NOP(); NOP(); NOP();
NOP(); NOP(); NOP(); NOP();
NOP(); NOP(); NOP(); NOP();
MeasuredReadingValue += ReadADC();
}
IntermediateValue1[Flag] = MeasuredReadingValue >> 4;
}
for (Flag = 0; Flag < 20; Flag += 1)
{
printf(" %u \r\n", IntermediateValue1[Flag]);
}
if(SampleNumber == 0)
Avg1 += MeasuredReadingValue/256 ;
else
Avg2 += MeasuredReadingValue/256 ;
Flag = 1;
}

 
Please Check.
 
--
Karan

Attached Image(s)

#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2020 APG vNext Commercial Version 4.5