• Hi all,

    I'm having some issues with the embedded ADC function, and was hoping to get some insight. I need to measure 0-10v, so I put together a simple voltage divider to scale that down to 0-1

    -My ADC is not registering different values, when fed 0.2v and 0.7v I received the same value.
    -Stability/Timing? I notice that my ADC values sporadically drop. I have tried with and without a 100ms pause, and with a 100nf capacitor, but this does not seem to help.

    def checkpin():
        adc = ADC()
        adc_c = adc.channel(pin= 'P13', attn=ADC.ATTN_11DB)
        for i in range(10):
            b = adc_c.voltage()
            v = 3.3*b/4096
            print(b,", ",v)

    An example output: (this does not change with different voltage input)

    348 ,  0.2803711
    3134 ,  2.524951
    3134 ,  2.524951
    142 ,  0.1144043
    142 ,  0.1144043
    3134 ,  2.524951
    142 ,  0.1144043
    3134 ,  2.524951
    3134 ,  2.524951
    3134 ,  2.524951

    Any thoughts/suggestions would be much appreciated. I have a ADS7818 which I can try uart with, but I'm just trying to determine the easiest way to measure 0-10v ±0.1

    Thank you

  • @b_rubble Here is a sample script using the ADS7818 with SPI:

    # Drive the ADS7818 ADC using SPI
    # Connections:
    # xxPy | ADS7818
    # -----|-------
    # P10  |  CLK
    # P11  |  CONV
    # P14  |  DATA
    from machine import SPI, Pin
    from ubinascii import hexlify
    spi = SPI(0, SPI.MASTER, baudrate=4000000, polarity=1, phase=1, bits=16)
    buf = bytearray(2)
    vref = 2.493 # measured at the ADS7818
    while True:
        # start a conversion and get the result back
        spi.write_readinto(b"\xe0\x00", buf)
        # extract the raw ADC value and derive Voltage
        value = ((buf[0] << 8) | buf[1]) & 0xfff
        volt = 2.0 * vref * value / 4096
        print(hexlify(buf), value, volt)
        res= input("Next: ")
        if res == "q":

    The conversion and reading back is done within the single spi.write_readinto() call. It is then easy to embed that in a small class.
    Note: Since the ADS7818 runs at 5V, insert a resistor of 3.3k to 10k into the data line back into the ESP32 to limit the current into the ESD diodes.

  • @b_rubble You can use the built-in ADC is the noise does not matter or if you can ignore the lower 4 bits.

    I have used an ADS1115 with an ESP8266, attached with I2C. It has a SMD package, but you can get modules at any size, down to a DIL8 pin layout. But this is a rather slow device. The ADS7818 is faster, and it should be possible to read that with SPI. UART won't work.
    So I do not know your application needs, speed or precision.

  • @robert-hh thank you very much for your insight. I have actually used some of your previous posts to help troubleshoot other issues, so I definitely appreciate you taking the time to answer. I modified my script to just output value, voltage and fed in a fairly consistent 420mv (measured as 419-421mv through my fluke). Unfortunately it seems that even with calibration there would be too much noise for my uses. I continue to get very odd behavior, so I think I will use an off the shelf ADC to accomplish this task.

    Do you have experience or suggestions for off the shelf converters? I don't have SMT capabilities with my current setup, but I do have a ADS7818 which I will try to use with UART.

    Thank you

  • @b_rubble The call to adc_c.voltage() returns a voltage scaled in mV, depending on the attenuation factor you have selected. That is 11db, so the range is about 0-3.3V. if you want to get the raw ADC values, you have to call adc_c.value() or simply adc_c(). That will return a raw value in the range of 0-4096.
    The ADC of the ESP32 is not very good. You get the best linearity at 6 dB attenuation, and the low offset is at about 70 mV.
    I cannot tell whether you see this much changing values. Besides high noise and non-linearity I did never observe such changes. It may be related to external factors like your circuitry, sockets, ....
    If I repeat the here on a LoPy4, I get plausible (albeit poor) values with you script, feeding 2V into P13. Note that only the first column is fine.

    1993 ,  1.605688
    2034 ,  1.638721
    1969 ,  1.586352
    1968 ,  1.585547
    1881 ,  1.515454
    1917 ,  1.544458
    1971 ,  1.587964
    1948 ,  1.569434
    2007 ,  1.616968
    1974 ,  1.590381

Log in to reply

Pycom on Twitter