9 years, 1 month ago.

AnalogIn read() function is giving erroneous results

Hello everybody,

In my setup I'm giving almost exactly 1.65 volts (DC) to pin20 (declared as AnalogIn) of LPC1768 mbed board. When I print this value, it shows highly erroneous results in each iteration. Even if I'm maintaining more than 5 seconds gap between successive iterations, it still shows incomprehensible output i.e. any value between 0.000 to 1.000, even though it should show something like 0.499, 0.486, 0.511, 0.503 etc. i.e. values that are close to 0.5.

I get similar errors using read(), read_u16().

A digital multimeter shows the expected voltage value i.e., the exact voltage of the wire connected to pin p20.

I would truly appreciate any help in finding a solution to my problem.

Thank you.

main.cpp

#include "mbed.h"

AnalogIn   ain(p20); // analog input on pin 20
DigitalOut gndPina(p15);
DigitalOut gndPinb(p16);
DigitalOut gndPinc(p17);
DigitalOut gndPind(p18);
DigitalOut gndPine(p19);
Serial pc(USBTX, USBRX);

int main() {
    pc.baud(921600);
    float Vin_eff;
    char str[100];
    char x = 'a';
    while(x != 's') {
        Vin_eff = ain;
        sprintf(str, "\nThe analog value detected is %2.3f volts.", Vin_eff);
        pc.puts(str);
        x = pc.getc(); 
    } // continue while loop until x = 's'
}

Question relating to:

Which values does it show, and how do you generate your 1.65V?

posted by Erik - 20 Mar 2015

@ Mr. Erik: I need to scale a 0-5 volt input to 0-3.3 volt range. This is then to fed to the ADC. For testing purposes, I generated 2.5 volts on a regulated DC power supply. I then fed it to my voltage divider circuit (R1 and R2 in series, with output voltage taken across R2.)

R1 = 330 kOhm resistor in series with 10 kOhm resistor = 340 kOhm;

R2 = 330 kOhm resistor in series with 330 kOhm resistor = 660 kOhm

Then the output voltage across R2 is fed to a unity gain buffer amplifier using single supply op-amp LT1006. The output of this op-amp is finally fed to pin p20 of my LPC1768 mbed board.

posted by Debasis Sahoo 23 Mar 2015

Apologies for the huge delay in replying. The moving average software filter as suggested by Mr. Staron works well enough for lab applications.

posted by Debasis Sahoo 28 May 2015

2 Answers

9 years, 1 month ago.

The analog inputs are VERY noisy on the Mbed 1768. There were several threads about this subject.
Look at http://developer.mbed.org/users/chris/notebook/Getting-best-ADC-performance/
I use a external ADC (MCP3708) when I need a clean signal, and a software filter for the internal ADC.
This is my filter:

my

/*the class  AdcFilter process a analog value (float)  and apply a  a filter
   1. filter big spikes  ( greater than delta)
	 2. filter random precision errors ( exponential smoothing
	 
	 this is NEEDED for the noisy adc  in the mbed 1768
*/

AdcFilter::AdcFilter() {
    y=0;
    init=false;
    //default values for a agressive filter
    delta=0.5;  // the value abs(x)<1  -> delta= 5% of the full value
    smooth= 0.01;
}
float AdcFilter::filter(float x) {
    if (!init) { //first sample
        y=x; //accept the sample
        init=true;
        return y;
    }
    //clear the spikes

    if (x > y+delta)
        x= y+delta;
    if (x < y-delta)
        x= y-delta;
    //smooth the high frequecy small errors (exponential smoothing)
    y = x*smooth + (1-smooth)*y;
    return y;
}

Accepted Answer

From the link you post, and also from my own experience, those noise problems can be pretty much completely eliminated by a good input signal and making sure there is no activity on neighbouring pins, preferably as also the question asker did by pulling them to ground.

posted by Erik - 20 Mar 2015

Thank you. I will try your software ADC filter solution, first.

posted by Debasis Sahoo 23 Mar 2015

@ Erik Olieman: How can I generate a good enough input signal? Detailed instructions are welcome. From my very limited experience: using op-amp and capacitor. Unfortunately, I do not currently have the time to deeply understand the intricacies of concepts like ground planes etc., despite my deep desire to truly understand this, which I plan to do a few months later. For now, a quick implementation of generating a good enough input signal for my the built-in ADC of my mbed LPC1768 board is badly needed.

Thank you for understanding.

posted by Debasis Sahoo 23 Mar 2015
9 years, 1 month ago.

I had a similar issue using the KL05Z AnalogIn. In my case I didn't have spikes but I needed to measure down to 1mV that was varying by +/- 20mV. I got round this by taking 100 samples in a loop adding them and dividing by 100. I now have a +/- 1mV fluctuation. If you have spikes first you will need to remove or ignore these. I would take a simple approach to this as there is a known issue with the LPC. Make two loops with 100 samples, first loop get the mean value which should be close to the actual value your looking for providing there are not too many spikes and these are relatively equal in quantity. Second loop, another 100 samples but reject any readings that are +/- 10% outside the mean value of the first loop.

If that doesn't work I would use an external A-D converter as Robert does or change platform.

Thank you Mr. Staron. I will try averaging, as you suggested, in addition to Mr. Spilleboudt's software filter and will post the results.

posted by Debasis Sahoo 23 Mar 2015

Assigned to Debasis Sahoo 9 years, 1 month ago.

This means that the question has been accepted and is being worked on.