Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Getting the best out of Pico ADC

Page 1 of 17
Author Message
Bleep
Guru

Joined: 09/01/2022
Location: United Kingdom
Posts: 419
 Posted: 06:06pm 13 Jul 2023 Copy link to clipboard Print this post

In another thread, Volhout mentioned the ADC and how with a bit of averaging you can get quite good results. I was wondering what would be the best method to get the best out of the Pico ADC?
I'm currently measuring some small voltages, so I'm amplifying them, I'm then doing the following.

Dim Float Iin(11),Volt(11),Iout(11)
Dim Float filtIi(11),filtIo(11),filtV(11)
Dim Integer y

'Take 12 readings, for the Iin, Iout and Volts find the median value
'Do this 12 times and then do the same again on those 12 values
For y=0 To 11
filtIi(y)=Math(median Iin())
filtIo(y)=Math(median Iout())
filtV(y)=Math(median Volt())
Next

' Filter out high and low readings again.
raw(0)=Math(median filtIi())
raw(1)=Math(median filtIo())
raw(2)=Math(median filtV())

Using the built in median, I beleive should order the values then take the middle 2 and average them, because there is a even number of samples.
This gives me reasonably good results and is fast, but I wondered if there was a better way? speed is not critical I'm only taking a sample per second, but I don't want the smoothing to swallow up too much time.
I originally was taking a group of samples, finding the largest and smallest, removing them and then averaging the rest, all in BASIC, so did take a fair time, but this median method seems to give me much more stable results.
Thanks for any input.
Regards, Kevin.

stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 1667
 Posted: 06:52pm 13 Jul 2023 Copy link to clipboard Print this post

When I first tried adc it was recommended to use an array and average it but I just use the samples or take one sample and case test it. I get good results.

TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5950
 Posted: 09:02pm 13 Jul 2023 Copy link to clipboard Print this post

Internally, the pico takes 10 readings, discards the two highest and the two lowest.
It then averages the remainder.

The only real advantage by doing it yourself is, the readings are spread over a longer time-frame. In 'some' cases, that is significant.

Jim
VK7JH
MMedit   MMBasic Help

Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3696
 Posted: 09:04pm 13 Jul 2023 Copy link to clipboard Print this post

The error in the pico adc is a non-monotonic fault al msb transition and msb-1 transition. When there is sufficient noise in the signal you can average to hide it.
Without noise, you can't. Regardless how many samples.

If you are measuring RMS ac signals, or fft the data the adc error is not dominant.

If you want to measure accurate dc voltages, you can substantially increase the adc performance by adding noise (i.e. play sound, choose noise, and in hardware attenuate the signal to 10 lsb or so. Add that to the input voltage, and average (100x or so)..
You may be able to achieve 5 digit resolution.

Professional multimeters average over 100ms. This automatically removes 50hz and 60hz noise.

Volhout
Edited 2023-07-14 07:16 by Volhout
PicomiteVGA PETSCII ROBOTS

phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 1853
 Posted: 10:54pm 13 Jul 2023 Copy link to clipboard Print this post

Another way to reduce the effect of the ADC fault starts with a low pass filter on the input (as low as your application can accept).
It should not be possible for the difference between adjacent samples to exceed the slew rate of the filter, so if it does it must be an error. Discard that sample and replace it with an an extrapolation of the preceding samples.
This does not work for an input that changes too slowly, so is best for AC rather than battery volts for example.

Edit
Taking inspiration from Volhout.
I guess adding a tone to the input at the filter corner frequency then averaging it out later might improve it.
Edited 2023-07-14 09:27 by phil99

Grogster

Joined: 31/12/2012
Location: New Zealand
Posts: 9137
 Posted: 01:26am 14 Jul 2023 Copy link to clipboard Print this post

I believe I read in the Pico manual, that the ADC will perform much better if you disable the on-board switch-mode regulator, and power the board from an external linear regulator.  I don't think I was dreaming about that.....
Smoke makes things work. When the smoke gets out, it stops!

phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 1853
 Posted: 01:48am 14 Jul 2023 Copy link to clipboard Print this post

With Volhout's method of error masking the extra supply noise might actually be useful!

Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3696
 Posted: 07:16am 14 Jul 2023 Copy link to clipboard Print this post

phil99 said  With Volhout's method of error masking the extra supply noise might actually be useful!

1/ No, noise will be proportional, meaning that when measuring a low voltage it would be 1 lsb, and high voltage 100 lsb.

2/ Pico PSU noise changes (peak peak, and spectrum) with load. Very inpredictable

3/ Have to look it up in the datasheets, but most likely the pico PSU switches at a frequency outside the frequency band of the ADC (500kHz fastest -> Nyquist is 250kHz).
Dpending input filter (or none) this may not work.

Resolution is what you gain by averaging.
Accuracy requires a reference.

The Pico reference is 3.3V. Generated from the power supply. So the measurement accuracy can never be better that the PSU is. The output voltage of the PSU changes with temperature, load (ARM working harder), video content (VGA pico), etc.. For best performance you use an LM4040 at the Vref pin. That will make you indendent of the PSU (ripple and drift).

It all depends on what you want to achieve. Colleagues of mine have succeeded to create a 3-3/4 digit (0. - 3999) accurate multimeter from an 8 bit flash ADC. This flash ADC used internally 2 x 4bit ADC's and a 4 bit DAC (2 ADC stages) so it was littered with linearity errors and non-monotonity. It required pulling out all the tricks there are... literally measuring each of the 256 steps of each ADC in production... and applying noise, and averaging and....(patent-ed)...

Success,

Volhout...
Edited 2023-07-14 17:17 by Volhout
PicomiteVGA PETSCII ROBOTS

Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3696
 Posted: 07:25am 14 Jul 2023 Copy link to clipboard Print this post

phil99 said  Another way to reduce the effect of the ADC fault starts with a low pass filter on the input (as low as your application can accept).

The input filter will smooth out the signal, removing disturbances.
It will not work to solve the ADC error, since it is produced AFTER the filter.
The averaging can remove it when (and only when) you have control over the input noise, that should be 5-10x larger than the error to be corrected. (100x is also possible, but requires significantly more averaging to restore the resolution).

phil99 said
I guess adding a tone to the input at the filter corner frequency then averaging it out later might improve it.

That will work fine, as long as you average over an exect number of cycles, though a triange wave is needed. Look at the distribution.

Volhout
Edited 2023-07-14 17:26 by Volhout
PicomiteVGA PETSCII ROBOTS

Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 5847
 Posted: 07:28am 14 Jul 2023 Copy link to clipboard Print this post

As this is a silicon fault there is no reliable workaround. It's far, far easier to use a different chip for your ADC inputs - use those to connect the chip. :)

Now we have a nice DAC to play with, I wonder if it would it be possible to have a "standard" external ADC chip supported by MMBasic? Actually, we already have one - the MX170 28-pin...
Mick

Preliminary MMBasic docs & my PCB designs

Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3696
 Posted: 07:44am 14 Jul 2023 Copy link to clipboard Print this post

Without tricks the MX170 is only 10 bits. Not much better than the pico ADC that is a "degraded" 12 bit ADC.

If you need a nice accurate ADC, use a TI ADS8326. Not very expensive, single channel 16 bit (1.5 lsb linearity) 100kSps SPI ADC. You can drive it with a 24bit (or more) SPI block running a MCLK of 2.4MHz (or lower, depending the speed you need it to work at).
With it's 0.65mm pitch it is however a bit tricky to solder. Best is to put it on a 8 pin DIL adapter PCB that you can buy for near nothing.

Volhout

P.S. but the earlier mentioned theory (accurate noise free Vref, noise free power supply etc..) apply always, and become more important when resolution increases..
Edited 2023-07-14 18:26 by Volhout
PicomiteVGA PETSCII ROBOTS

phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 1853
 Posted: 08:30am 14 Jul 2023 Copy link to clipboard Print this post

Once again my explanations are incomprehensible to anyone but me.

Quote  It will not work to solve the ADC error, since it is produced AFTER the filter.

The purpose of the filter is not to solve the ADC problem but to make it stand out so the defective samples can be removed. Any changes from sample to sample that are larger than the filter slew rate will allow must come from within the Pico. They can then be removed.
This only works while the input is changing at a sufficient rate. A static input could be at a voltage that gives a constant error which would go undetected. Adding some ripple at a suitable frequency will ensure it is always changing.

Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3696
 Posted: 08:58am 14 Jul 2023 Copy link to clipboard Print this post

Hi Phil,

Thanks for the explanation. Let me try to explain the ADC error, then you may reconsider.

picture this:
The ADC is 12 bit, Vref = 3.3V
Each LSB is 3300/4096 = 0.805mV

when I apply 1.64919 V the reading of the ADC is decimal 2047
when I add 0.805mV (1.649995V) the reading should be 2048, but in fact it is 2051
then I add another 0.805mV, then the reading should be 2049, and in fact it is 2049.

This is (roughly) what is happening at the MSB change. The magnitude is different per chip.

I guess if you want to filter this kind of behaviour out, then you should design your input filter to allow maximum 1 lsb change per reading of the ADC (3 lsb should be flagged as impossible).

At maximum speed (500kHz) you would (2us) allow a maximum input change of 4096x2 = 8ms.
At the same time you would have to evaluate all individual samples.

It can be done.

When slowing down a bit. If you want a settling time of 1 second (is 5 tau) then you could work with 200ms first order filter (R-C) and sample the ADC at 20kHz. MMBasic could be able to keep up with that pace.

But what if you connect at stable voltage of 1.649995V. No lsb change. Just a stable 2051 output, where it whould have been 2048. ???

Volhout
Edited 2023-07-14 19:05 by Volhout
PicomiteVGA PETSCII ROBOTS

Bleep
Guru

Joined: 09/01/2022
Location: United Kingdom
Posts: 419
 Posted: 11:51am 14 Jul 2023 Copy link to clipboard Print this post

This is becoming an interesting tread, if you are into electronics, which I am. :-)
From the above, it looks like I'm probably getting about as good as I can possibly get with the ADC as it is, I'm measuring the voltage off of a 100A current shunt and am able to get 50mA resolution, ie I can increase the current by 50mA and consistently see a change in the output from the ADC, after my filtering as above, which would appear to be as good as I'll ever get.
My question really was is there anything that software can do, massive oversampling, filtering, short term running average..... that can improve on the 9bits (claimed) accuracy that we are left with, without resorting to extra hardware?

I know in theory Median isn't ideal, which was why I was asking, however the way it works, in that it orders the data values, takes the middle two values and average them (in my case, as I'm using an even number of data values), I then do all of this twice so 144 data samples per output result.
Median seems to work quite well for me as I suspect I have a lot of noise (static inverters, long cable runs etc..) and throwing away most of the data seems to be a good thing and gives me a reasonably stable result, which other methods I'd tried did not. :-)
Regards, Kevin.
Edited 2023-07-14 21:52 by Bleep

phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 1853
 Posted: 12:13pm 14 Jul 2023 Copy link to clipboard Print this post

Quote  But what if you connect at stable voltage of 1.649995V. No lsb change. Just a stable 2051 output, where it whould have been 2048. ???

Yes, that is why I suggested adding an AC component to the input, so you never have a stable voltage. I guess a triangle wave with a rate of change similar to the max. slew-rate of the input filter would make the errors visible. Once the out-of-limits samples are removed the AC component can be averaged out.

stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 1667
 Posted: 12:45pm 14 Jul 2023 Copy link to clipboard Print this post

I run my picos from 3.3V linear regs and 3.3V enable grounded.
I have a 5 button a-d board , for arduino 5V but works fine as a game controller with pico.
bp!=pin(31)
'if bp!<3.1 then 'a button has been pressed
select case bp!
case <.02
'left pressed
case 1.5 to 1.8
'right pressed
case 0.3 to 0.6
'up pressed
case 0.9 to 1.1
'down pressed
case 2.3 to 2.5 'fire button
end select

I have waveshare pico with 160x80 screen and a simple scope and just touching the a-d pin and the 50Hz noise clips the display, ie > 3.3V

lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3036
 Posted: 02:51pm 14 Jul 2023 Copy link to clipboard Print this post

Don't know if this is the appropriate thread, but I have an ADC question. I have a one-turn pot. If I multiply the value returned by 100 and set an integer to the result, I get values ranging from 1 to 233--so far so good.

But from 1 to halfway around, the range is 1-8; and to a little over 3/4ths of the way, to 21. Then the remaining quarter-turn ramps quickly up to 233.

With this program:

setpin 31,ain
dim integer i,j,k,l,m,n
do: i=pin(31)*100: if j<>i then: j=i:?i;" ";:endif:pause 1000:loop

I get this as I turn the pot (for instance):

10  15  17  21  37  66  234  233  15  14  12  8  5  1  5  6  10  11  21  13  6  1  6  8  9  8  10  11  10  12  11  13  20  33  126  235  233  232  19  18  21  20  27  30  29  47  44  42  41  65  64  63  62  113  111  110  108  107  106  104  103  228  230  229  233  231  233  8  7  30  25  1  7  8  7  8  17  22  21  20  21  31  52  51  30  20  19  228  231  6  31  41  16  15  31

What kind of pot do I have? What kind do I want if I'd like it to ramp up in a more regular fashion?
PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed

stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 1667
 Posted: 03:24pm 14 Jul 2023 Copy link to clipboard Print this post

lizby said  Don't know if this is the appropriate thread, but I have an ADC question. I have a one-turn pot. If I multiply the value returned by 100 and set an integer to the result, I get values ranging from 1 to 233--so far so good.

But from 1 to halfway around, the range is 1-8; and to a little over 3/4ths of the way, to 21. Then the remaining quarter-turn ramps quickly up to 233.

With this program:

setpin 31,ain
dim integer i,j,k,l,m,n
do: i=pin(31)*100: if j<>i then: j=i:?i;" ";:endif:pause 1000:loop

I get this as I turn the pot (for instance):

10  15  17  21  37  66  234  233  15  14  12  8  5  1  5  6  10  11  21  13  6  1  6  8  9  8  10  11  10  12  11  13  20  33  126  235  233  232  19  18  21  20  27  30  29  47  44  42  41  65  64  63  62  113  111  110  108  107  106  104  103  228  230  229  233  231  233  8  7  30  25  1  7  8  7  8  17  22  21  20  21  31  52  51  30  20  19  228  231  6  31  41  16  15  31

What kind of pot do I have? What kind do I want if I'd like it to ramp up in a more regular fashion?

What's a one-turn pot?

Bleep
Guru

Joined: 09/01/2022
Location: United Kingdom
Posts: 419
 Posted: 03:51pm 14 Jul 2023 Copy link to clipboard Print this post

I assume this is over several turns of the pot? In which case I'd say you have a single turn logarithmic pot, so you are going off the end and back each turn.
You probably want a linear pot and only go round once, well actually only about 3/4 of a turn max.
Regards

Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 3696
 Posted: 04:12pm 14 Jul 2023 Copy link to clipboard Print this post

Lizby,

You are measuring an audio potmeter. These have a non-linear curve sometimes referred to as logaritmic potmeter.

Normally there is a mechanical stop. But that seems missing.

Volhout
Edited 2023-07-15 02:14 by Volhout
PicomiteVGA PETSCII ROBOTS

Page 1 of 17