Thursday, August 11, 2016

ESP8266 - Internal ADC 2 - the easy way example



This is just a very quick example on how to add a Voltage Divider to the ESP8266 Internal ADC input to increase the ADC input range.

For more theory behind, please take a look at the previous related article: ESP8266 - Internal ADC


Today project:

      Measure a voltage input range from 0-5V with the ESP8266 internal ADC


What do we need:

  • 2 Resistors for the voltage divider, R1=105.6k, R2=24.08k. I am using here precision resistors and the values are measured values with a proper calibrated bench meter.
  • a good, trustable, calibrated ok Multimeter.
  • some wires to connect all together.


I will not insist on connections, take a deeper look at the previous article about


Voltage divider schematic and Vout (ADC input voltage) formula




How do we do it :


1. Measure your Max desired input voltage
    In my case, Max Input Voltage (Vmax) = 5.1919 (measured)



 
2. Measure Resistors values:
    R1 = 105.6k
    R2 = 24.08k


 
3. Check if Full Scale Value at the voltage divider output is inside the ADC defined domain:
  • Calculated : Vout = (R2/(R1+R2))*Vin = 0.964072733 V
  • Measured = 0.96038V
     Good enough for the precision we are looking for. ESP8266 ADC is 10bit only and not exactly the most accurate in town



4. Calculate Voltage Divider Ratio:
  • Vdivider Ratio= Max Input Voltage/Fullscale value =  5.405976676



5.  Read ADC value : 
       adcr = adc.read(0)
      print("    ReadADC     : "..adcr)
     Average result for adcr = 1017

THIS IS IMPORTANT !! It tell us that we are inside the ADC domain as adcr < 1024 !

IF adcr > 1023 then you need to adjust your voltage divider resistors to fit inside ADC domain!



6. Calculate LSB  in 2 ways to cross check that we have the right value:
  • LSB = Input Voltage read by multimeter/ADC readed Value = 
                   =  5.1919 / 1017 =  0.005105113 V
      OR
  • LSB = (ADC Input  pin read Voltage by multimeter/ADC readed Value/)*Vdivider Ratio = 
                  = (0.96038/1017)*5.405976676 = 0.005105113 V
       It looks that we have the right LSB Value for our exercise!

     If you want to know also the ADC LSB, then
       LSB = ADC Input  pin read Voltage by multimeter/ADC readed Value  =   
                =  0.96038/1017 = 0.000944346 V

    Guess what's happening if you multiply ADC LSB with Vdivider ratio :)




7. Software Implementation for the ADC read function:

 function readADC()
      ad = 0
      LSB = 0.005105113 --calibrate based on your voltage divider AND Vref!
      adcr = adc.read(0)
      ad= adcr*LSB       
      print("    ReadADC     : "..adcr)
      print("    Read Voltage     : "..ad)
      return ad
end

and some results in the terminal window:

> SENT: readADC()
readADC()
    ReadADC     : 1017
    Read Voltage     : 5.191899921
>






14 comments:

Unknown said...

Tracker,

Thank you very much. I will recheck everything tonight with this information.

Mike

Unknown said...

Tracker,

I believe your LSB calculation is backwards. Should is be

•LSB = Input Voltage read by multimeter/ADC readed Value

So

5.1919 / 1017?

Thank you,

Mike

Unknown said...

Hi Mike,
Yes, you have right, the calculation was done in the correct way. Typo error, corrected. Thanks for spotting.

LSB = Input Voltage read by multimeter/ADC readed Value
5.1919 / 1017 = 0.005105113 V

Did you managed to obtain the right values for your setup?

Unknown said...
This comment has been removed by the author.
Unknown said...

Thank you very much for the example. It worked perfectly.

One thing though. I'm monitoring the voltage of a solar panel, The max voltage of the panel is actually 6v, so I calibrated everything for 6v. I noticed when the voltage gets down to about 2v there is a greater discrepancy in the readings. From 6v to 3v my reading are about +/- 20mV off from what my meter reading is. From 3v to about 2.3v my reading are about +/- 50mV to 60mv and below 2.3 my readings are off by about +/- 100mV to 150mv. Granted I won't be powering anything below 3.5v so the accuracy below that is not important, but is it normal that the further the voltage moves away from the maxV that the accuracy decreases?

Thank you again for your help.

Mike

Unknown said...

Hi Mike,

Nice to hear that helped you with your project.
Your errors are mostly comming from the non-linearity of the ADC and other factors that are not counted in such a simple example.
For the precision of the ESP8266 ADC and voltage reference, I think you have obtained very good results.

If you want more precision then can use a dedicated high-resolution ADC as I have on my AN-1 extension board (take a look on the nEXT EVO section above) or a dedicated Power Monitor IC as in the BMS (battery monitor system) example.

After playing a while with ADC's & stuff I decided to use a dedicated IC solution for my Solar Panels monitor. If interested, drop me an email and we can talk about. Want to keep the comments section clean and at the subject.

Jeffy said...

It is really a great and useful piece of info. I’m glad that you shared this helpful info with us. Please keep us informed like this. Thank you for sharing.

SEO Training in Chennai

Unknown said...

I keep on reading your blog post.. This was still amazing. Thanks a lot for sharing this unique informative post with us.. I really enjoyed by reading your blog post

Seo Training

Stelios S. Koroneos said...

Tracker,

thank you for all the info you shared.
I am thinking of using the esp8266's ADC to measure the output of an oxygen sensor.
The sensor outputs max 200mV so is within the ADC's range, but what i am concerned is about the resolution of the build in ADC.
I need minimum 33uV resolution which the 10bit does not give so i need to oversample it (as in your examples) to at least 12bit.
Based on your experience how stable the build in ADC will be?
I am asking as i see that lots of people at end start using external ADC's

thanks in advance for your time

Stelios

Unknown said...

Hi Stelios,

For something like that I would suggest you to use a external ADC with a higher resolution like MCP3421 or similar.

You can take a look at the links below for more details, driver examples, etc:

1. http://www.esp8266-projects.com/2015/04/18-bit-adc-mcp3421-i2c-driver-esp8266.html
2. http://www.esp8266-projects.com/2016/03/esp8266-adc-input-frontend.html
3. http://www.esp8266-projects.com/2015/12/p3-esp8266-next-evo-analog-extension.html

Yurii said...

Let me share my experience with ESP’s internal ADC. I have a couple of those modules. One is soldered on development board Devkit 1, 0 and contains ESP…12E. Another one is just a bare module without development board and is named ESP…07 (with external antenna port). I have discovered that on an ESP 12 ADC works just fine. An AnalogRead(A0) value is more or less proportional to the voltage applied to the ADC pin. However on ESP 07 the situation is different. The value of AnalogRead(A0) is not proportional to voltage. It changes according to some unknown function. So far I have not find an explanation to this. Will try to rewrite firmware and see whether it helps.

JB said...

Well, I found the problem. I turned out that that strange behavior of ESP07 was caused by the use of low quality materials – breadboard and dupont wires (still don’t know which one of these was causing more trouble). Because of that ground pin of ESP07 was not firmly connected to the ground and that led to strange results. With ground floating ADC started measuring voltages only from around 140mV up to 1.2 volts and the readings were not stable. After fixing this issue everything works as it should. So far

goan said...

ADC characterization (IMAGE)


I performed a characterization of the ADC of my ESP-12 that is reported in the figure. It seems to have an offset error of almost 50 mV and a gain error around 5%. In order to get the corrected voltage after acquiring values through system_adc_read() function provided in the API, I just use this formula:

uint16_t adc_val = system_adc_read();
float adc_volt = (adc_val/1024.0+0.0458)/0.949;

At the moment I'm not able say nothing about the repeatability of this characterization yet. As said previously by other users this can be due to the use of low quality materials, however it is possible that all the boards of the same serie show similar performance. I will give updates after testing different ESP-12 modules.

Adhuntt said...

Very Effective blog thanks for sharing Instagram and Facebook have provided an amazing place for new brands to grow and flourish. We can find the perfect niche for your brand on the best social media platforms.

Post a Comment