adc woes

  • I'm trying to measure the voltage of a 16v DC supply by applying it to an analog pin via a 100k/4k7 voltage divider. My multimeter shows the pin sitting at exactly 721mV. But when I run

    import time, machine
    for i in range(9):'P20'); v=val.voltage(); print(v, ' ', end='')

    I'm seeing 10mV of variation

    693  691  701  692  702  701  691  700  701  >


    import time, machine
    for i in range(10):
     for i in range(10):'P20'); v=val.voltage(); Vav+=v
     print(Vav/10, ' ', end='')  


    694.1  696.2  695.7  694.6  693.5  695.4  695.5  692.6  694.6  694.4  >

    but still 3.5mV (0.5%) variation. I really need 3 significant figures for this, what am I missing?

  • @kjm So you are averaging over 1000 values. You can also use a low pass filter, which is a little bit simpler
    See also the lessons and analysis by Bernd Boser:
    and especially
    which shows a noise of about 25 LSB. So your averaging of 1024 values (25*25=625) matches that. B.t.w: good ADCs have a noise <= 1 LSB.

  • I couldn't get any improvement with a 100nF ceramic across the 4k7 but did better with brutish code

    import time, machine
    for i in range(8):
      for i in range(128):
        for i in range(128):'P20'); v=val.value(); Vav1+=v
        av=Vav1/128#; print(av, ' ', end='')
      x=Vav2/128; print('%.0f' % x, '  ', end='')
    2687   2687   2687   2687   2687   2688   2687   2687   >

  • @kjm You miss nothing. The ADC of the ESP32 is bad. It helps a little bit, if you add a low impedance capacitor (e.g. 10 nF Ceramic) with short leads as close as possible to the ADC input you are using.
    Besides that: If you need low noise, good precision and linearity, use an external ADC.

    Note: You do not have to re-init the channel in the loop all the time.

Pycom on Twitter