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
    adc=machine.ADC()
    for i in range(9): val=adc.channel(pin='P20'); v=val.voltage(); print(v, ' ', end='')
    

    I'm seeing 10mV of variation

    693  691  701  692  702  701  691  700  701  >
    

    Averaging

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

    helps

    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:
    https://github.com/bboser/IoT49
    and especially
    https://github.com/bboser/IoT49/blob/master/doc/analog_io.md
    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
    adc=machine.ADC()
    for i in range(8):
      Vav2=0
      for i in range(128):
        Vav1=0
        for i in range(128): val=adc.channel(pin='P20'); v=val.value(); Vav1+=v
        av=Vav1/128#; print(av, ' ', end='')
        Vav2+=av
      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