Introduction: ESP8266 ADC - Analog Sensors

Picture of ESP8266 ADC - Analog Sensors

ESP8266 modules have the capacity to perform many useful tasks. GPIO pins can be manipulated based on digital signals to do all sorts of handy things.

Expanded firmware such as NodeMCU have made these modules very flexible and have transformed them into fully capable micro-controllers.

Now, the ESP8266 v7 and v12, include an ADC (Analog digital converter) pin. This means that the ESP8266 module can process inputs from analog sensors. Light sensors, rheostats, force sensors, etc.

This is loosely comparable to an Arduino 'Analog IN' pin.

With an ADC capability, instead of just ON or OFF, the ESP8266 can read a range.

Step 1: Prepare Your ESP8266.

My presumption is that you could utilize the ADC pin with the default firmware if you are schooled sufficiently in bit banging. I don't have the knowledge or patience.
NodeMCU has a "read.adc()" function built in. Easy.
So, flash your module with NodeMcu.
I use lualoader with Win7 to flash and manage these modules with good success.

Step 2: Connect the Analog Device.

Picture of Connect the Analog Device.

Connect your analog sensor as you would with an Arduino. For testing I am using a generic 10K 'slider' rheostat.

Connect you sensor wire to the ESP's ADC pin.

Step 3: Boot Up the ESP

Picture of Boot Up the ESP

Once booted up, using lualoader, you can read/monitor the ADC TOUT pin. Use either 'read' or 'autorepeat read'. The values will be echoed in the main window.

The datasheet describes the ADC pin as having 10 bit resolution. This means 0 to 1024. You should get a value somewhere within this range.

Here the fun begins! Apparently, the module only converts voltage between 0 and 1 volt.

As an example, I have a 10k rheostat hooked up to the ADC pin. Fully moving the slider to the position where I would expect a 0 reading, the ADC TOUT pins reads 13~15, not 0 but encouraging!

However, as I slide the slider to the right, I see the ADC TOUT reaches the maximum reading of 1024 in about 1/3 the distance.

Ideally, I want the slider to register 0 to 1024 increasing or decreasing over 100% of the slider travel.

Reaching the maximum reading in 1/3 of the travel makes sense, the ADC pin only reads up to 1 volt. Any reading over that, say 1.1v to Vcc of 3.3v will be maxed out to 1024.

So, I need to supply the ADC pin a voltage between 0 and 1 volt only.

Using a voltage divider greatly improves the situation.

Step 4: Add a Voltage Divider

Picture of Add a Voltage Divider

For R1, I used a 220R and for R2, I used 100R resistors. On my voltmeter the actual resistance was 225 and 103.7 respectfully. The math indicates that 220R and 100R should divide 3.3v to 1.03v. 225R and 103.7 should be ~1.04v. All very close. On the breadboard, my voltmeter is reading .98v.

This relationship should hold true for 22R and 10R as well as 20K and 10K. However, caution! the small ones heat up. The larger ones utilize the full range of the slider but the readings are only a few hundred apart.

Using 220R and 100R seem to work, my slider now reads from ~10-13 on the low end to 1024 and the range has a steady progression through 100% of the slider travel.

I suspect that replacing one of these resistors with a trim pot in the same range would give me the ability to fine tune this slider to the full 0 to 1024 range.

Step 5: ADC on an ESP8266-01 ?

Picture of ADC on an ESP8266-01 ?

If you are very good with a soldering iron, this ADC capability can be accessed on any version of the ESP8266. The above graphic is the pinout for the EX chip. The chip on the ESP-1 has the pinout, just not the physical connection. Some steady hands and a small iron could tap it.

Some observations that could save you heartburn:

- These modules are not breadboard friendly and not just because the pins are too close together. Simply plugging in a connection lead or bump the tx rx connections can cause errors. Just bumping the breadboard can be problematic. These chips are very sensitive to voltage fluctuations. Hours of hair pulling and chasing the ghost in the machine was solved by soldering as much as possible. Soldered connections have provided a rock solid controller.

- 3.3 volts and lots of it. 630ma. If you use a lm1117t3.3 regulator (I do.) Solder it! If the ground becomes loose or is wiggled, your 3.3v can spike. Under-voltage will cause the ESP to reboot. Too much voltage will cause smoke.

- Coding formats in the NodeMCU api may or may not work in your script. I.e. wifi.sta.setip(), use '=' not ':'.

- You can use your Arduino UNO as a serial device, however, your UNO puts out 5v at both the tx and rx pins. Some sources state that the ESP8266's GPIOs are tolerant. tx and rx are not. Use voltage dividers and diodes or some other magic. Besides, if you have to use an Arduino for your project, use an Arduino. As this product matures, perhaps you wont need an Arduino.

- The NodeMCU Server mod has serious memory leaks. These leaks cause the board to reboot when memory gets too low. Insert 'print(node.heap()' in your script and watch the memory reduce as you access the page. As the "Heap" depletes, the ESP will reboot. This memory leak can be greatly reduce or eliminated by resetting all variables to 'nil' at the end of your script. However, if your script terminates early for some reason, the memory is used until 'reset' This may or may not be a problem for your project.

Also, the "Heap" button in LuaLoader, appears to not give accurate memory readings.

There is a great discussion here:

- Pins 4 and 5 as labeled on my ESP-12 are reversed in LuaLoader. That is, if you want to read or switch pin 4, you will need to assign the task to pin 5 in LuaLoader and for pin 5 you will need to assign pin 4.

With the ability to program digital pins, read analog pins, store and run multiple scripts with NodeMCU's firmware. This platform becomes a capable and very economical alternative for your IoT projects.

I hope you have found this instructable helpful!


diy_bloke (author)2016-11-17

"Over-voltage will cause the ESP to reboot. Too much voltage will cause smoke."

A typo i presume. 'Under voltage' causes the reboot

Richard_H (author)2016-03-16

Thanks for the Instructable - especially pointing out that the ADC pin actually exists on all the versions, you just need to solder to the IC pin directly.

What ADC sample rate have you found is possible? I've seen mixed reports, some that suggest it is possible to get up into the 44kHz range.

calibrearun made it! (author)2015-09-06

Sir this is my block diagram,Here each sensor with the ESP will generate its own unique ip.

My doubt is whether the ESP will have an inbuilt os.

In case of no i am going to coordinate these IPs in raspberry pi with CONTIKI OS for real time management.

Here doubt is whether the pi is capable of handling CONTIKI and in which tool i can work for programming for this. and how can i work with the Coap protocol or MQTT.

Then the connected sensor IPs and the real time management is going to be connect with lelylan cloud and it can be monitored and also controlled by the help of lelylan.

ashikch (author)calibrearun2015-11-19

I mean You can install Webserver and SQlite databse in Yocto Linux or any other Linux distro for sure!! I don't know about CONTIKI :(

ashikch (author)calibrearun2015-11-19

Such a aGood Article!! I think you can use web server installed with SQLite database on Rasberry pi. In that way you can create a website easily and an APP easily. Rather than fiddling with 3rd party database this is best option. But, it requires some scripting to use Database tables and PHP for sure.

LucasF24 (author)2015-10-17

Correction, it's 0 to 1023. There are 1024 possible values from a 10-bit decimal system and 0 is counted as one.
1024 = 100 0000 0000 (11-bit number)
1023 = 11 1111 1111 (10-bit number)

breagan22 (author)LucasF242015-10-18

Your are correct sir! Thank you for pointing that out!

breagan22 (author)2015-09-07

Using ESP with NodeMCU, you will then have a robust OS on the module that you can program with LUA. You can bypass the Raspberry PI.

NodeMCU has a MQTT module (library). Connect the ESPs directly to the Lelylan Cloud MQTT Broker. Publish the data and MAC or ChipID to 'id' the sensor.

As the data is sent to the Broker, you can use CONTIKI to manage the data.

calibrearun (author)2015-09-05

Hai sir here i am working in WSN in industrial IOT.can you prefer any way of prototype that i can develop from ESP.

breagan22 (author)calibrearun2015-09-06

Can your question be more specific?

breagan22 (author)2015-03-25


I admire the work you have done! Outstanding!

As to your question about the 3 sensors. Yes, you can do this with only an ESP-12. However, your current diagram is problematic.

1. Your temperature sensor looks like a DHT11? This is actually a digital sensor. The NodeMCU has a great library that may work with this. The library, I think is written for the DHT22. I have been using this nonstop on an ESP-12/1 for weeks 24/7 with a DHT22, very stable. It will work the way you have it attached.

2. Your soil sensor looks strictly analog. Your current connection will on yield a 0 or 1. This sensor will work with the ADC pin. You will need to do some testing to find the right resistor combination and document the range of the readings. A lua version of Arduino's map() would be nice.

3. I am unable to determine if your light sensor is digital or analog. I suspect the one depicted is digital. The current connection will work, IF you can find a NodeMCU library for that sensor. OR you can modify an existing library. As an alternative, a LDR is a very simple (cheap) analog device and you could also use the ADC pin for that.

4. Your RGB Led will work fine.

So, you can plug multiple devices into your ADC pin. However, you will need to multiplex them.

For example, in your current diagram, for the soil sensor, move the sensor wire (Blue) to the ADC pin, add a diode, and set GPIO13 to LOW.

Assuming the light sensor is analog, Also connect the sensor wire (yellow) to the ADC pin, add a diode. Attach Vcc to a GPIO, say GPIO4 and set that GPIO4 to LOW. Attach GND to ground.

In your script set GPIO13 to HIGH ( completes the circuit ) read the ADC pin and then reset GPIO13 back to LOW. ( opens the circuit ). Then set GPIO4 to HIGH and read the ADC pin then reset to LOW.

Essentially, power the sensor, read the ADC PIN and turn off the sensor, move to the next sensor and repeat.

Your can access as many analog sensors as you need. You will need to add delays after setting the pins to HIGH to give the sensors time to register.

Keep up the good work!

Akin Yildiz (author)breagan222015-03-27

check this out, i did some progress ;)

i can read data from the sensor and turn on/off an led from a broswer, and also display the value..

id = 0

print( will give the sensor reading


pin = 7


gpio.write(7,gpio.HIGH) or

gpio.write(7,gpio.LOW) will turn on/off the LED on gpio13.


lua commands;

gpio mapping;

however displaying the sensor value online stable needs more work,

breagan22 (author)Akin Yildiz2015-03-27


You are on the right track! Consider moving the red wire to the LDR from CH_PD to a GPIO. That way you can turn the LDR on and off the same way as the LED. (allowing multiple analog sensors at the ADC pin).

To you script add:

lightVal =

-- further down:

buf = buf.."LDR reading: "..lightVal

Your LDR reading will be printed to your webpage.

Also, with lightVal you can turn your led on or off based on its value.


If lightVal > 900 then

Akin Yildiz (author)breagan222015-03-27

ok so with the new line

buf = buf.."LDR reading: "..lightVal

i can display the value, but there is no way for me to refresh this value, because my initial connection is a

conn:on("receive", function(client,request) [line_12]


conn:send (i believe this is the issue, because right now the connection stays on and only listens to messages from the browser - does this make sense?)
i'm a true beginner so please bare with me :) BUT if we change it to conn:send then i wont be able to control the LED from the browser, is there a way to do both at the same time.?!

where/what line should I add to this code to be able to refresh this value; (line 32 added)


breagan22 (author)Akin Yildiz2015-03-28

Move: lightVal = from line 4 to somewhere below line 10: "conn:on("receive", function(client,request)" and before you use it in line 32.

Everything between function(client,request) and client(close) is processed (refreshed) every time you access or 'refresh' your web page.

As it is now lightVal is assigned when the ESP does dofile("webapp.lua"), this value is static until webapp.lua is processed again. Moving the function into the client.request area process with each page access or refresh.

As you progress, all of the work turning sensors on/off and reading them will take place in this area.

Akin Yildiz (author)breagan222015-03-29

very nice, it worked.. you should definitely do a multiple analog sensors instructable..!!!
this is life changing, i can build a web controllable smart outlet this way for under $10 :)

breagan22 (author)Akin Yildiz2015-03-29

Ha, I'm glad it is working for you. Love to see light bulbs in the brain come on!

Oh, here is the multi sensor instructable.


Akin Yildiz (author)breagan222015-03-27

im trying this now as we speak. how many analog sensors could we connect this way?

breagan22 (author)Akin Yildiz2015-03-27

Yes! exactly!
I believe you will need to add a diode in your sensor's yellow wire and a diode in other sensors attached to the ADC. They need to be isolated when turned off.

Theoretically, there is no limit to the number of analog sensors you could attach this way. However, and there is always a however, we are severely limited by the size of the script and memory used by the variables holding the readings. we could make some good estimates with two or three. my wild guess is that you could add at least ten. Maybe. :)

Perhaps another instructable showing multiple sensors is in order?

Akin Yildiz (author)breagan222015-03-27

is this what you meant by the new wiring.?
so does this mean that each analog sensor shares the ADC pin with one leg, but if we put the other leg to a GPIO we can add many analog sensors.? with a resistr/gnd as well.

thank you for all the help.. i will be doing a detailed post with a new device soon once I get everything together.. i will be linking your profile and this post so we can get some views here :)

The Expert Noob (author)2015-03-24

any recommendations for an iron for such small pins? I've been wanting to activate dsleep() for my ESP-1 but the pins are impossible to solder to with my huge tipped iron.

Omnivent (author)The Expert Noob2015-03-26

A short length of soft copper wire around 2..4mm in diameter twisted tightly around the regular tip, with the end reaching a bit out (perhaps bended down for better control) - file to a blunt edge and tin immediately. Won't last forever, but quick and easy to redo - for better heat transfer, a separate wire could be wound on the outside. You and your file must negotiate the size of the new tip - hope you agree :)

I might attempt to attach a sewing needle to my iron. Possibly, twisting some copper wire around the tip to hold the needle will conduct enough heat. Can you flux just the wire to soldered?

Akin Yildiz (author)breagan222015-03-25

hey let me know about the needle to the iron move, sounds like a solid plan. if you can get a good grip with the needle, enough surface to touch and hold.!! i think i'm going to give this a try. i hope they make these esp chips ready for deep sleep in the near future, sounds like a huge issue.

thank you for your help breagan. i will look more into what you've suggested with the wiring/code. all the sensors will be analog, this was just to show a bit everything easier, including the rgb. i actually have used a DHT11 as an analog sensor and it works great. no libraries. i am trying to avoid libraries as much as i can. i just need to collect raw data and upload it to thingspeak. that's it. no conversions needed, a very simple code. 3 analog sensors, and an rgb led (analog again). read data from sensors, turn corresponding LED on (blink every 5 secs). and also upload this data to the cloud. and go to deep sleep. repeat this every 6hrs (4x/day). that is all i need. check this out, this genious person got 3 sensors connected to ESP-01;

dmwatkins (author)2015-03-25


About This Instructable




More by breagan22:ESP8266 WiFi OTA Remote File ManagementESP8266 - NodeMCU - CPU Speed TestESP8266 Irrigation Controller / Echo Alexa integration
Add instructable to: