New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent values when using "analogRead()" #92

Open
josmunpav opened this Issue Dec 12, 2016 · 23 comments

Comments

Projects
None yet
@josmunpav
Copy link

josmunpav commented Dec 12, 2016

Hi,

I checked yesterday the new implementation of analogRead and values are pretty incosistent. Not sure if it is because of the implementation of the method or just because the ADC on ESP32 is not very accurate.

I created a simple several stage voltage divider to read on. Source was the 3.3V output pin of the ESP WROOM 32. Then I applied 3 different steps with 4.7K 1% tolerance resistors. Values measured with the multimeter:

P1: 3.286V --> Expected = 4095 / ADC output = 4095
P2: 2.462V --> Expected = 3071 / ADC output = 2811
P3: 1.641V --> Expected = 2047 / ADC output = 1814
P4: 0.819V --> Expected = 1021 / ADC output = 823

Any explanation to this? I though the levels would go from 0 being 0V and 4095 being top of the range 3.3V

I need to rely on an accurante ADC for my project so any help is welcomed. Cheers!

@me-no-dev

This comment has been minimized.

Copy link
Member

me-no-dev commented Dec 12, 2016

I did not go into depths with measuring the result, but I have seen similar results on the ESP31B. As far as the code goes, there isn't much that can be changed :) we ask the hardware to measure the level on given channel, and it returns the value to us. I have made sure that pins are properly initialized and all possible pulls have been disabled.
It is also possible that the ADC has internal reference voltage which is not 3.3V. I'll ask around

@josmunpav

This comment has been minimized.

Copy link
Author

josmunpav commented Dec 12, 2016

Many thanks for the prompt answer. Now that you mention it I think I saw some thread on the official forum talking about different levels on ADC initialization and internal voltage references and some guy also complaining about poor results. I think it was related to test version of ESP31 so I kind of hoped these issues were addressed.

I have got the feeling if I want accurate results I am going to head for a dedicated ADC IC :(

@me-no-dev

This comment has been minimized.

Copy link
Member

me-no-dev commented Dec 12, 2016

That guy complaining was probably me :)
What I can tell is that results are constant, so there is some logic behind, just not what we are expecting it to be. BTW if I want good ADC, I would go for dedicated chip also ;)

@josmunpav

This comment has been minimized.

Copy link
Author

josmunpav commented Dec 12, 2016

Lol btw you are making a great work on this Arduino port ;-)

This is just me being a little bit pushy but any idea of when can we expect analogWrite?

@me-no-dev

This comment has been minimized.

Copy link
Member

me-no-dev commented Dec 12, 2016

I'm waiting for the last PWM driver to be documented and prepped in IDF. There are currently 3 options that you can use for PWM already available.

  • LEDC (16 channels) < its basically PWM
  • SigmaDelta (8 channels) < it is SigmaDelta which is great for LEDs and others
  • DAC (2 channels) < outputs actual analog signal
//SigmaDelta Setup(pin 16, channel 0)
sdSetup(0, 10000);//channel, frequency
sdAttachPin(16, 0);//pin, channel
//SigmaDelta Write
sdWrite(0, 128);//channel, 8bit value

//LEDC Setup(pin 17, channel 5)
ledcSetup(5, 10000, 16);//channel, frequency, bits
ledcAttachPin(17, 5);//pin, channel
//LEDC Write
ledcWrite(5, 1024);//channel, bits value

//DAC (pins 25 or 26)
sdWrite(25, 128);//pin, 8bit value
sdWrite(26, 65);//pin, 8bit value
@hcs-svn

This comment has been minimized.

Copy link

hcs-svn commented Dec 12, 2016

OK, that explains my confusion last weekend :-)
I've attached a TMP36 and got results that I did not expect.
I can confirm that the results are constant and that they depend on the voltage that I supply to the analog input pin (in my case 36).

My tests also showed 4095 for 3.3V and 0 for 0V
For voltages around 0.6V the ADC value was lower than expected.

@me-no-dev

This comment has been minimized.

Copy link
Member

me-no-dev commented Dec 12, 2016

if someone has a digital potentiometer, maybe we can make up the logic behind ADC reads

@projectgus

This comment has been minimized.

Copy link
Member

projectgus commented Dec 12, 2016

Any explanation to this? I though the levels would go from 0 being 0V and 4095 being top of the range 3.3V

Do you get better results if you use lower resistor values (ie 1K or 470 ohm)? There will be some internal impedance to the ADC when it takes a sample (I don't actually know how much but can find out). ~4.7K input impedance may be enough to pull the measured voltages down slightly..

Another way to test this theory is to put a small capacitor between the ADC pin and ground, the extra capacitance should prevent the voltage from drooping when the ADC samples from a high impedance source like the resistor divider.

EDIT: This theory doesn't really explain the TMP36 result @hcs-svn mentions, as the sensor has a low impedance output already - unless there's a resistor between the sensor output and the ADC pin.

@josmunpav

This comment has been minimized.

Copy link
Author

josmunpav commented Dec 13, 2016

I have just connected the output of the voltage divider to a high precision opamp (LMC6482) used as a buffer to eliminate any kind of error.

Ouput of the buffer is clean at 2.462V which should be around 3070 but ADC still reads a value close to 2785, even less than before :(

I doubled check the ouput of 3V3 pin and is giving 3.286V so the error is still quite huge, close to 10% according to my tests.

Hope we can get some light here

Update: My initial test was using GPIO35.
Second test is using GPIO14, getting now 2810 on average
Third test is using GPIO4, getting again 2810 on average

@igrr

This comment has been minimized.

Copy link
Member

igrr commented Dec 13, 2016

The ADC frontend indeed has a non-linear response. Once characterization data is ready, we will take it into account inside ADC APIs, and update the datasheet with correct values of INL/DNL and effective resolution.

@bobik78

This comment has been minimized.

Copy link

bobik78 commented Mar 23, 2017

Privet @igrr ,
Do you know when characterization data will be ready?
Also, basically when calculating the voltage while using 11db attenuation should I refer to VDD_A voltage as a max. voltage or full scale voltage of 3.9[v] in my calculations? There's a note in IDF documentation - " At 11dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage." which confused me a little.
Thanks,
bobik78

@markterrill

This comment has been minimized.

Copy link

markterrill commented Jun 18, 2017

This is critical for me, due to a temperature sensing application. I'm wishing to port from Particle Photon P1, though not being able to analog read accurately would be a show stopper. Very keen to hear if this has been fixed.. ?

@vseven

This comment has been minimized.

Copy link
Contributor

vseven commented Aug 31, 2017

Like @markterrill I also am looking to do temperature sensing applications with the ESP32. So I'm assuming the addition of broken in idf label means not much can be done? From the ESP32 page (https://www.esp32.com/viewtopic.php?t=1045 ) it seems like they were going to add something to the firmware to make this better. It also looks like using a lower attenuation (-6db) and using a range of 0.1v - 1.8v will get you mostly linear results. I have yet to test this however.

@bobik78 - It means if the input voltage is 3v3 (which it is) then your hi range for the 11db is 3.3 and not 3.9 as its rated. I agree...its a little confusing. Personally I've found it a little lower then that in practice, anything about 3.2ish pegs it at 4095.

@vseven

This comment has been minimized.

Copy link
Contributor

vseven commented Sep 6, 2017

@copercini - "Broken in idf" means no software fix?

As a followup I cannot get a NodeMCU ESP32-s board to take the commands to change the read width nor the attenuation: https://esp32.com/viewtopic.php?f=19&t=2881&sid=fdffa84f0fd6047bb6a588d2baf6dcdc . It seems to just ignore the commands even though it compiles and uploads fine from my sketch. Does this also not work? And if so how do I make my attenuation 6db instead of 11db since 11 is so noisy?

@copercini

This comment has been minimized.

Copy link
Collaborator

copercini commented Sep 6, 2017

@vseven it just means that is no problem in the Arduino layer (this repository) but the solution needs to come from IDF first to be implemented here

This issue was open before attenuation workaround, maybe now some examples how to use it in Arduino will be great! Please make a PR if you get any progress :D

Edit: you are redeclaring the funcions in your code of esp32 forum, please take a look at this post https://esp32.com/viewtopic.php?f=19&t=2881#p13712 it show the correct calling of adc functions

@copercini

This comment has been minimized.

Copy link
Collaborator

copercini commented Sep 6, 2017

@vseven Try these:

    analogReadResolution(12); //12 bits
    analogSetAttenuation(ADC_0db);  //For all pins
    analogSetPinAttenuation(A18, ADC_0db); //0db attenuation on pin A18
    analogSetPinAttenuation(A19, ADC_2_5db); //2.5db attenuation on pin A19
    analogSetPinAttenuation(A6, ADC_6db); //6db attenuation on pin A6
    analogSetPinAttenuation(A7, ADC_11db); //11db attenuation on pin A7
@vseven

This comment has been minimized.

Copy link
Contributor

vseven commented Sep 6, 2017

Thank-you @copercini - the problem was I was trying to call them outside of a function, which failed, which I then was declaring them thinking that would work (lack of knowledge on my part). I moved the statements in your example to within my setup() and now it's compiling. I haven't tested it yet but I'm assuming it will work.

Side note: Something else that was confusing me...the Arduino IDE shows analogReadResolution in red but analogSetAttenuation in black so I thought I was typing something wrong. Is this normal?

image

@copercini

This comment has been minimized.

Copy link
Collaborator

copercini commented Sep 6, 2017

The orange thing is because the arduino IDE have a list of "known functions", like AnalogReadResolution and AnalogRead. The "analogSetAttenuation" isn't in that list since it is a function that only works on ESP32. But there are some tricks to set "analogSetAttenuation" as orange too. Don't worry about it, it's just a visual thing.

Your code comments are really nice, if you make an example with this stuff will help a lot of people! fell free to make a PR

@vseven

This comment has been minimized.

Copy link
Contributor

vseven commented Sep 6, 2017

I'll see what I can do about examples but as you can tell I'm a little inexperienced. 10+ years of VB.Net programming makes this stuff look like Greek to me.

Oh...my results in case anyone cares: https://esp32.com/viewtopic.php?f=19&t=2881&p=13739#p13739

@markterrill

This comment has been minimized.

Copy link

markterrill commented Sep 14, 2017

awesome work. thanks.

@mhaas

This comment has been minimized.

Copy link

mhaas commented Nov 15, 2017

Hey there, it looks like idf now contains a calibration method: espressif/esp-idf#164 (comment)

Does that fix this issue? I am thinking about getting some esp32s..

@Morgan679

This comment has been minimized.

Copy link

Morgan679 commented Oct 8, 2018

Hi, inesp32wemos lolin oled , I can only use the GPIO36 and GPIO39 when i use wifi, the others porst reading bad values!!!!!!
I need help please !!!

@lbernstone

This comment has been minimized.

Copy link
Contributor

lbernstone commented Oct 9, 2018

@Morgan679 : ADC2 is not available while WiFi is running (https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html#overview). ADC1 is pins 32-39.
I have posted some code that demonstrates how to use ADC calibration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment