Extending the ESP-01 – Weirder Pin Magic

One of the target projects I have is to re-implement a door sensor to be wifi enabled. To do that I was going to add an ESP to an Arduino, but thought I could probably squeeze the two digital lines for ‘100% open’ and ‘100% closed’ into something that wouldn’t conflict with the pullup resistors of the ESP-01. Basically something that would read two lines on GPIO0.


This is almost the inverse of reading an analog value on a digital pin (driving a capacitor to charge, then waiting for it to discharge).


I had the idea that if I could encode two analog values into one digital line I might have something. One way to do this is similar to what radio-controlled toys do; they send a series of variable length pulses in between a longer guard timer. With only two values I don’t really need a guard timer, either – I just need to encode the digital-high duration as one value and the digital-low duration as the other value, and then time the two states.


And to do that encoding? How about a bunch of resistors on the two magnetic sensors (for the open and closed states on both) and use those to influence an astable 555.


I’d like to say it worked the first time I wired it up. It didn’t – the breadboard was crappy. As soon as I realized that and moved the project a bit it worked. After some tweaking of the capacitor and resistor values, I had something that was workable. Try this site to see what I mean:¬†http://www.learnabout-electronics.org/Oscillators/osc44.php

To estimate the frequency and components, I used this site: https://www.allaboutcircuits.com/tools/555-timer-astable-circuit/

This is what it looks like:

The 555 and ESP-01

There is a bit more going on there; from bottom to top:

  • A BitScope Micro oscilloscope is below the breadboard
  • The 555 and resistors (and tangle of jumpers) are at the bottom-middle.
  • There are a couple of buttons on the board which reset the ESP and set flash mode
  • The blue PCB in the middle is a 3.3V power supply for the ESP
  • The red PCB is a Sparkfun logic level shifter
  • The black PCB at the top is the ESP-01
  • The FTDI (serial-to-USB board) is at the top to the right of the breadboard.

The output of the 555 circuit looks like this:

The 555 in astable mode

If you squint a bit you’ll see it’s running nearly at a 50% duty cycle; just on either side of 150ms for both high and low times.


Now the fun part; with one ISR and micropython, this is what the timings look like, updated once a second on the serial console:

Output of the micropython timer in the REPL

The output in the serial console reads as:

C: Count of seconds out of 5000 (it quits after 5000)

S: Samples taken (also, the number of interrupts)

H: Milliseconds GPIO0 spent at digital HIGH

L: Milliseconds GPIO0 spent at digital LOW


Which matches what the ‘scope is showing; around 150 milliseconds for both readings. It did take a little futzing to select resistors that would balance out like this, and be large enough values to give the system some immunity to noise.


Anyway, once I get the code cleaned up I’ll post it to gitlab. If you’re thirsty, it looks like this:

from machine import Pin
import utime

tStart = utime.ticks_ms()
tHigh = 0.0
tLow = 0.0
count = 0
cmax = 5000
samples = 0

def pinDelta( event ):
    global tLow
    global tHigh
    global tStart
    global samples
    if p0.value() == 1:
        tLow =  (tLow * 0.8) + (utime.ticks_diff( utime.ticks_ms() , tStart) * 0.2)
        tHigh =  (tHigh * 0.8) + (utime.ticks_diff( utime.ticks_ms() , tStart) * 0.2)
    tStart = utime.ticks_ms()

p0 = Pin(0, Pin.IN)

p0.irq(trigger=Pin.IRQ_RISING + Pin.IRQ_FALLING, handler=pinDelta)

print('Starting measurement...')

alarm = utime.ticks_add(utime.ticks_ms(),1000)

while count < cmax:
    if utime.ticks_diff(alarm, utime.ticks_ms()) < 0:
        alarm = utime.ticks_add(utime.ticks_ms(),1000)
        print ("C:",count,"/",cmax," S:",samples," H:", int(round(tHigh)), " L:", int(round(tLow)) )
        count += 1



I almost forgot, the magic of reading the two states via the 555 is to use the two separate switches to control the resistance  of either side of a voltage divider that controls the timing of the 555 on pin 7. The simple way to do this is to have a resistance when the switch is open, and closing the switch adds another resistor in parallel, on each side. It looks like the drawing below. Ignore the resistance values and use the calculator above.


The interesting bit is the left side of the schematic.