ESP8266 ADC - Analog Sensors

191,358

113

25

Posted

Introduction: 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.

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: tech.scargill.ne

- 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!

Share

Recommendations

  • Microcontroller Contest

    Microcontroller Contest
  • Science of Cooking

    Science of Cooking
  • Pocket-Sized Contest

    Pocket-Sized Contest
user

We have a be nice policy.
Please be positive and constructive.

Tips

Questions

22 Comments

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

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

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.

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)

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

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.

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

Can your question be more specific?

Akin,

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!

check this out, i did some progress ;)

https://gist.github.com/yildak/66b210174517564c765...

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

id = 0

print(adc.read(0)) will give the sensor reading

&

pin = 7

gpio.mode(7,gpio.OUTPUT)

gpio.write(7,gpio.HIGH) or

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

.

lua commands; https://github.com/nodemcu/nodemcu-firmware/wiki/n...

gpio mapping; https://github.com/nodemcu/nodemcu-firmware/wiki/n...

however displaying the sensor value online stable needs more work,

httpserver.jpgrev-12wiring.jpg

Akin,

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 = adc.read(0)

-- 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.

example:

If lightVal > 900 then
gpio.write(7,gpio.LOW)
else
gpio.write(7,gpio.HIGH)
end