Reading Random Digital Data from AD4681 ADC

Thread Starter

EricUBC

Joined May 12, 2023
27
Hello all,

I am currently working on a custom PCB design that requires the use of an ADC to convert 0-12V to a digital value that can be processed by a Fx2837 MCU. The ADC I am working with is an AD4681. I am having issues with reading values correctly either due to specific timing constraints, a problem with the design, or a faulty component. I will try and provide as much info I have available to make the problem clear and welcome all feedback.

What works: I can convert 0-12V input voltage down to 0-3.3V to be measured by the ADC and have verified the input pins receive this voltage. I am able to communicate to the ADC via SPI commands, both giving instructions and reading data off of the SDO line. I have given it instructions to output the converted data measured from both inputs simultaneously via one line as a 32-bit number. I can divide the data up to two 16-bit numbers that represent the input voltage for each of the two inputs.

That's where things stop working as expected. The data is random, as if the input pins are floating. I have checked connectivity and can assume that the device is properly soldered to the board and there is no short between the differential pairs. The positive pin sees the 0-3.3V input voltage and the negative pin is connected to ground. But my data bounces around and I cannot convert the digital signal to useable code. The data is given to me in twos-compliment format and I have code that converts it accordingly. I shouldn't be measuring negative numbers regardless, but that seems to be the case 75% of the time.

What might be wrong: Based on the schematic in the datasheet, I should have put a capacitor from the negative input to ground. This seems like a noise filtering consideration and not a defect, but am open to other's interpretations. Otherwise, I don't see anything that could point to the design being the problem. Unfortunately, because it is a surface mount component and the negative input lines connect to the ground pad underneath the device, I cannot cut the trace and test a capacitor to ground. I do hope that this is not an indication of where the problem is.

The other potential risk is the timing constraint of measuring valid data. The ADC requires the CS line to be cycled to create a latency before being cycled again when reading the data off SDO. The time of converting the data internally is 190ns, but I have an innate delay of 20ms after toggling the CS line. I would need to adjust the clock frequency of the MCU in order to make it closer to 190ns, but based on the datasheet, it just seems like I need to wait 190ns before reading the converted data by issuing a dummy command to generate the necessary SCLK signal to push the data onto SDO. As long as I read the data within a frame of toggling CS, I feel like my code should be sufficient.

Clearly that is not the case though, as I receive data indicating it isn't measuring the potential difference to any degree of accuracy. It doesn't even appear to be a case of data corruption that could benefit from CRC, as there is no clear pattern between the input voltage and the random values. I have attached a snip of code that gives a little more detail as to what I am trying to accomplish.

Any help and feedback is appreciated. Beyond telling me the design requires a cap to ground on the negative terminal as that sounds like game over to me.
 

Attachments

nsaspook

Joined Aug 27, 2009
13,312
Just doing a quick read of the datasheet to look at the configuration registers.
A quick guess of things I would check. Make sure you can write and read the device configuration registers correctly.
Make sure the CRC is set the way you want, the proper Vref voltage source is selected (external Vref) and the SPI is using the correct SPI mode (1-wire, conversion data, looks like SPI_MODE_1 is needed).
Code:
//ADC Build
    GpioDataRegs.GPACLEAR.bit.GPIO19 = 0xFF;
    delays_loop(1000);

             //5432109876543210
    adcCMD = 0b1010000100000000;
    spia_xmit(adcCMD);
    delays_loop(1000);

             //5432109876543210
    adcCMD = 0b1001000000000010;
    spia_xmit(adcCMD);
    delays_loop(1000);

    GpioDataRegs.GPASET.bit.GPIO19 = 1;
    delays_loop(1000);

    adcCMD = 0b0000000000000000;

    for(;;)
    {
        GpioDataRegs.GPACLEAR.bit.GPIO19 = 0xFF;
        delays_loop(100);
        GpioDataRegs.GPASET.bit.GPIO19 = 1;
        delays_loop(100);

        GpioDataRegs.GPACLEAR.bit.GPIO19 = 0xFF;
//        delays_loop(100);

        spia_xmit(adcCMD);
        delays_loop(1000);

        while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) {
            adcAz = SpiaRegs.SPIRXBUF;
        }

        spia_xmit(adcCMD);
        delays_loop(1000);

        while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) {
            adcEl = SpiaRegs.SPIRXBUF;
        }

        GpioDataRegs.GPASET.bit.GPIO19 = 1;
        delays_loop(100);

        // Return value is twos-compliment, convert to negative voltage if MSB = 1
        if((adcAz & 0b1000000000000000) == 0b1000000000000000) {
            adcAz = adcAz & 0b0111111111111111;
            adcAz = ~adcAz + 1;

            azVoltage = ((float)adcAz/5461.25) * -1;
        }
        else {
            azVoltage = (float)adcAz/5461.25;
        }

        // Return value is twos-compliment, convert to negative voltage if MSB = 1
        if((adcEl & 0b1000000000000000) == 0b1000000000000000) {
            adcEl = adcEl & 0b0111111111111111;
            adcEl = ~adcEl + 1;

            elVoltage = ((float)adcEl/5461.25) * -1;
        }
        else {
            elVoltage = (float)adcEl/5461.25;
        }
 
Last edited:

Thread Starter

EricUBC

Joined May 12, 2023
27
Just doing a quick read of the datasheet to look at the configuration registers.
A quick guess of things I would check.
Make sure the CRC is set the way you want, the proper Vref voltage source is selected (external Vref) and the SPI is using the correct SPI mode (1-wire, conversion data, SPI_MODE_1).
Currently not utilizing the CRC and it defaults to being disabled. I did issue an instruction to select an external reference voltage of 3.3V, which I verified with a multimeter as well. And I properly selected 1-wire configuration, which is verified by me receiving 32-bits of data on SDO when toggling CS and seeing nothing on the SDOB/ALERT line.
 

Ian0

Joined Aug 7, 2020
9,844
Why such a complicated circuit? Why not just a simple potential divider? Why the external reference when there is already one built in?
 

Thread Starter

EricUBC

Joined May 12, 2023
27
You really need a MSO scope to see what's really happening on the wires.
That seems like an ideal tool to have. I'm currently only able to use a logic analyzer or o-scope separately, though have only been using the logic analyzer. I can provide samples when I have access to the equipment again.
 

Thread Starter

EricUBC

Joined May 12, 2023
27
Why such a complicated circuit? Why not just a simple potential divider? Why the external reference when there is already one built in?
It is my understanding that using op amps with low tolerance resistors is more accurate, and a 3.3V reference provides more resolution. Accuracy is important in this case, though don't claim to be an expert so if there was a better way that is as accurate, I'd love to learn about it.
 

Thread Starter

EricUBC

Joined May 12, 2023
27
How more accurate than low tolerance resistors in a potential divider?
The op amps add offset and noise.
Not necessarily.
The built-in reference should provide all the accuracy and resolution that the A/D can intrinsically provide.
Appreciate the information. There is indeed an unintended offset I will need to account for in software. I'll remove them in a future edition of the board.

In what case would an external reference be appropriate?
 

nsaspook

Joined Aug 27, 2009
13,312
Appreciate the information. There is indeed an unintended offset I will need to account for in software. I'll remove them in a future edition of the board.

In what case would an external reference be appropriate?
What you need is stability with a high resolution SAR. The external Vref is usually much better than the internal one. Resolution, accuracy and precision are the keys to repeatable measurements. Compare the drift factors between them to make a wise choice.
https://forum.allaboutcircuits.com/threads/super-moon-shine.100322/post-898439
The internal VRef can be very good.
 
Last edited:

Ian0

Joined Aug 7, 2020
9,844
It is my understanding that using op amps with low tolerance resistors is more accurate,
Every component you add increases the error. It's like ΔS>0 - the second law of thermodynamics.
In your case, you have spent £7 on a fancy op-amp: it has a nice low offset (525μV), and fairly low voltage noise (6nV/√Hz) but the current noise (900fA/√Hz) combined with your 30k resistors increases it to 28nV√Hz. It has a bias current of 1μA which flows in your 30k resistors, generating an offset of 30mV. That's 1% error over 3.3V.

and a 3.3V reference provides more resolution.
Your new reference has a 0.05% tolerance, compared to 0.08% from the A/D, and the temperature coefficient of the internal reference is 10ppm/°C compared to 30ppm/°C for your external reference. What is the tolerance of your resistors?

Accuracy is important in this case, though don't claim to be an expert so if there was a better way that is as accurate, I'd love to learn about it.
A simple resistive divider is better.
 

Ian0

Joined Aug 7, 2020
9,844
If I look up FX2387 the only MCU I find is TI's TMS320F2837 which has a built-in 16-bit ADC. If I have the right microcontroller, why are you using an external ADC?
 

Thread Starter

EricUBC

Joined May 12, 2023
27
I'm using the internal ADC for other peripherals. Not all channels, but my understanding was that external ADCs are marginal improvements to using the internal ADC so I chose to isolate the prioritized input voltage line. Perhaps it is over kill and feeding the internal ADC through a resistor divider is sufficient, but my research led me to believe it would be worth it to use an external one. Seems I need to get better at using specific devices characteristics than generalities.
 

AnalogKid

Joined Aug 1, 2013
11,055
The net effect of the input circuit is a 30 K input impedance and a forward gain of 0.825. If the 30 K impedance is important (as in required by whatever is producing the input signal), then a 2-resistor attenuator followed by a simple voltage follower will produce the same low output impedance with fewer components, fewer error terms, and lower noise. And, you can cover both inputs with one dual opamp, eliminating U4.

Separate from that, why do the input circuit and A/D input have different grounds? Shouldn't the analog input conditioning stage be referenced to the same potential as the analog converter input? As it is now, any potential difference getween the two grounds, which mostly will be noise, will appear on top of the input signal at the A/D input.

Correction - The forward gain is 0.275, not 0.825.

ak
 
Last edited:

drjohsmith

Joined Dec 13, 2021
852
I'm using the internal ADC for other peripherals. Not all channels, but my understanding was that external ADCs are marginal improvements to using the internal ADC so I chose to isolate the prioritized input voltage line. Perhaps it is over kill and feeding the internal ADC through a resistor divider is sufficient, but my research led me to believe it would be worth it to use an external one. Seems I need to get better at using specific devices characteristics than generalities.
just to look at the original question:
you say " issues with reading values correctly "

what do you mean by that.

You have an input range , what happens when you apply a fixed voltage abotu mid range.
do you readback a constant value,
what is the voltage you apply and the value you read back ,

There are three places that things can go wrong, and we need to localize:

a) the input / circuit can be wrong
b) the way the serial data is received can be wrong
c) the way the serial received data is decode to a voltage number can be wrong.
 

nsaspook

Joined Aug 27, 2009
13,312
If I look up FX2387 the only MCU I find is TI's TMS320F2837 which has a built-in 16-bit ADC. If I have the right microcontroller, why are you using an external ADC?
https://www.google.com/search?q=microcontroller+adc+errata&rlz=1C1CHBF_enUS1007US1007&sxsrf=APwXEdeIg9L60W0-d4ErzebtjTH4viGGYA:1683998981200&ei=BclfZJTmC73Y0PEP7sqU0Ao&oq=microcontroller+adc+eratta&gs_lcp=Cgxnd3Mtd2l6LXNlcnAQARgAMgcIIRCgARAKOgoIABBHENYEELADOgQIIxAnOgoIABCABBAUEIcCOgUIABCABDoGCAAQFhAeOggIABCKBRCGAzoFCCEQoAFKBAhBGABQ4AVYlhVgqzpoAXAAeACAAYIBiAGuB5IBAzQuNZgBAKABAcgBCMABAQ&sclient=gws-wiz-serp

Internal microcontroller ADC's are notorious (ESP32) for having bad errata and subpar specifications because of fab process related compromises with mixed signal on mostly digital devices. A 16-bit ADC is not always The 16-bit ADC needed.
https://www.digikey.com/en/articles/iot-microcontrollers-have-adcs-know-when-apply-an-external-adc
Microcontroller ADCs
Any peripheral on a microcontroller must cope with the advantages and limitations of the process technology the semiconductor is built upon. Peripherals such as timers, parallel I/O ports, and communication interfaces such as SPI, I2C, and UART interfaces are very compatible with a CMOS digital process technology.

However, an ADC is an analog peripheral. Internally, analog peripherals such as ADCs or comparators require a capacitor which is not available on a pure digital process. This means using a mixed-signal process technology. Since a microcontroller is primarily a digital semiconductor and speed is important, the mixed-signal technology used must not sacrifice digital speed for analog functionality or performance characteristics. While this balancing act is achievable for common applications, for high-end analog applications this can limit the performance of the analog peripherals. Devices that are mostly analog, such as single-chip ADCs, may only contain slow digital logic at less than 1 megahertz (MHz). This allows the device to be built using a mixed-signal process that primarily benefits the analog.
 
Last edited:

Ian0

Joined Aug 7, 2020
9,844
The ESP32 is spectacularly bad on this front, and it astonishes me that it has been known about for so long yet a new, improved version has not appeared.
The micros that I have used (NXP, Renesas) perform on that front as specified, although other peripherals make their appearance in the errata!
We don't as yet know that the 16-bit ADC is required for.
 

nsaspook

Joined Aug 27, 2009
13,312
The ESP32 is spectacularly bad on this front, and it astonishes me that it has been known about for so long yet a new, improved version has not appeared.
The micros that I have used (NXP, Renesas) perform on that front as specified, although other peripherals make their appearance in the errata!
We don't as yet know that the 16-bit ADC is required for.
I'm not astonished, the ADC design was a bad copy. It's cost money, time, effort and talent to make it right while still keep their majority digital MOS production process in specification. It's a commodity, lowest cost uC, so most users don't care.
 

Ian0

Joined Aug 7, 2020
9,844
I'm not astonished, the ADC design was a bad copy. It's cost money, time, effort and talent to make it right while still keep their majority digital MOS production process in specification. It's a commodity, lowest cost uC, so most users don't care.
That explains it. It's made by a company I haven't heard of. I stick to the big name companies - that used to mean that you could always get stock!
 
Top