ESP8266: Handling analog signals without an analog input, just GPIO!

Experimenting with the ESP8266 at one point I came across the need of dealing with analog signals. There are a lot of versions of the module and most of them have GPIO accessibility but not ADC access. Some of the lates versions of the module have ADC though, but I have a few modules in stock that do not have it. And I need ADC handling.

Well, it is totally possible and here is how to do it.

There are 4 basic things that need to be done:

  • convert the analog signal into pulse width modulation (PWM)
  • read the PWM on any GPIO
  • read the PWM duty cycle on the ESP8266
  • calibrate the PWM to analog level response

This module can be purchased at my Tindie store


I am using NodeMCU Lua API. Lets look in more detail:

Convert the analog signal into pulse width modulation (PWM)

This is quite simple. The popular LM555 will do the trick. Here is the circuit:

Screen Shot 2015-04-20 at 11.37.38 AM

A sawtooth signal ramping up from 0 to 5v simulates the analog signal, the 555 spits out a PWM, with duty cycle proportional to the analog level. The 555 output is then connected to a GPIO pin.

Read the PWM on any GPIO

This is even simpler. Just pipe the output of the 555 to any GPIO pin.

Read the PWM duty cycle on the ESP8266

To do this, watch for the GPIO pin ‘up’ and ‘down’ events:

file.writeline([[gpio.trig(pin, 'both', callback)]])

In the callback function, read the pin, track the time when the up and downs happen and calculate the ratio, that is the duty cycle:

file.writeline([[time_read= time_read-time_base]])
file.writeline([[if cnt == 0 and rp == 0 then low_start=time_read]])
file.writeline([[if cnt == 1 and rp == 1 then low_end=time_read]])
file.writeline([[if cnt == 2 and rp == 0 then high_end=time_read]])
file.writeline([[high_start = low_end]])
file.writeline([[if (high_end-low_start) > 0 and cnt == 3 then]])
file.writeline([[duty = (100*(high_end - high_start))/(high_end-low_start)]])
file.writeline([[print("Duty: " .. duty) ]])
file.writeline([[cnt = 0]])

Read the PWM duty cycle on the ESP8266

Finally, pick a few calibration points between the PWM duty cycle you are reading and the actual analog signal value and calibrate the reading.

My prototypes are available on Tindie.

About hbouzas

Born in Buenos Aires, Argentina. Studied Physics at the University of Buenos Aires. Joined Schlumberger in February 1985 in Houston, Texas, and worked in several technical and managerial positions until 2000. From 2000 until 2008 held several management positions in Abingdon, UK; Calgary, Alberta and London, UK. Worked in the areas of Geophysical Exploration, Geological Modeling, Structural Modeling, Reservoir Modeling and Petroleum Economics and holds several patents. He is currently the Norway Technology Center Manager for Schlumberger Information Solutions and is based in Oslo and Stavanger. Main interest are software, technology, innovation, 3D visualization, design, human computer interaction, energy, environment.
This entry was posted in Uncategorized. Bookmark the permalink.

1 Response to ESP8266: Handling analog signals without an analog input, just GPIO!

  1. Pingback: DIY Memo: ESP8266 v12 analog I/O – Fujihita

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s