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.

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

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.

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

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

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 ?

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!

2 People Made This Project!


  • Made with Math Contest

    Made with Math Contest
  • Multi-Discipline Contest

    Multi-Discipline Contest
  • Robotics Contest

    Robotics Contest

22 Discussions


2 years ago

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

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


3 years ago

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.


4 years ago

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)

1 reply

Reply 4 years ago

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


4 years ago on Introduction

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.


4 years ago on Introduction

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

1 reply

4 years ago on Introduction


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!

9 replies
Akin Yildizbreagan22

Reply 4 years ago on Introduction

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,

breagan22Akin Yildiz

Reply 4 years ago on Introduction


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 Yildizbreagan22

Reply 4 years ago on Introduction

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)


breagan22Akin Yildiz

Reply 4 years ago on Introduction

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 Yildizbreagan22

Reply 4 years ago on Introduction

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 :)

breagan22Akin Yildiz

Reply 4 years ago

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 Yildizbreagan22

Reply 4 years ago on Introduction

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 :)


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.

2 replies

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?