Post Go back to editing

Ad5933 analog front end - 4 electrode measuring

Hey everyone,

I need to implement a four electrode measuring circuit to interface with the Ad5933.

Ive used the suggested analog front end in the attached link, which is very popular throughout the references:

www.instructables.com/.../

My problem:

Im able to calibrate a 1k resistor but whenever I change the load after calibration it shows very little difference, for instance an avg of 1040 ohm instead of 1000 ohm when I plug a 2k resistor.

Sometimes it shows even a lower avg value.

My setup:

For the opamps I ised TL072 and for the inamp I used INA118P. both are have suitable specs for the job.

I used 1M resistor for R current and R protect and used Rin of 2k and Rfb of 1k.

Ive fed the inamp and opamps with v+ of 10v and v- of negative 10v.

Ive attached all grounds in the system.

I short circuited all the ad5933 vdd pins and have them 5v vdd from an arduino, and did the same for the ground pins and attached to the common ground.

The ad5934 is controlled via the arduino by attaching a4 and a5 pins to scl and sda pins.

Finally ive attached a 1k resistor as the load between the four electrodes. Each pole of the resistor gets two parallel electrodes.

Ive checked my wiring a hundred times and Ive tried to add Rg to the inamp.

Ive tried to play with rfb and r in.

Ive chexked with a scope in every point to see that the signal is what its supposed to be. Im sure its good until the inamps input, where im not quite sure because I get very low voltage different across the input pins (20mv).

I would cery much appreciate guidance

Ben

Parents
  • It is had to suggest much without seeing the exact schematic with all connections and component values. Referring to a general sketch in your link, first suspect to check would be the DC working point for the entire schematic as the AD5933, generally speaking, requires the AC signals to have zero line at Vdd/2 = 2.5V in your case. Can you check if the DC voltage is 2.5V at:
    1. The left pin of Rcurrent resistor
    2. The output of the Vref Generator
    3. The right pin of Rprotect
    4. The left pin of Rin
    5. The RF pin of the AD5933
    ?
    If all is well, can you check that the AC voltage at the RFB pin of the AD5933 is a well-formed sinewave without any distortion or clipping at 0V or Vdd or both?
    Also, what settings are you programming into the AD5933? Excitation voltage, PGA gain, frequency range, number of settling cycles, etc.? 

  • Hey  Snorlax, Thanks for your reply!

    Im attaching an image of the schematics to make it more clear.

    regarding your questions, I have checked for vdc of 2.5v at all the points you suggested and it is indeed 2.5v.

    I do see some kind of clipping at the rfb pib and I cant seem to understand why it happens. it clips the lower part of the wave.

     my settings:

    supply voltage 5v

    Excitation voltage: 2.24v dc offset with vpp of 3v

    PGA gain=1

    frequency range 50Khz-52Khz

    default number of settling cycles 

  • and if I may, I'd like to add the Arduino code for the full picture:

    /*
    ad5933-test
        Reads impedance values from the AD5933 over I2C and prints them serially.
    */
    
    #include <Wire.h>
    #include "AD5933.h"
    
    #define START_FREQ  (50000)
    #define FREQ_INCR   (100)
    #define NUM_INCR    (20)
    #define REF_RESIST  (1000)
    
    double gain[NUM_INCR+1];
    int phase[NUM_INCR+1];
    
    void setup(void)
    {
      // Begin I2C
      Wire.begin();
    
      // Begin serial at 9600 baud for output
      Serial.begin(9600);
      Serial.println("AD5933 Test Started!");
    
      // Perform initial configuration. Fail if any one of these fail.
      if (!(AD5933::reset() &&
            AD5933::setInternalClock(true) &&
            AD5933::setStartFrequency(START_FREQ) &&
            AD5933::setIncrementFrequency(FREQ_INCR) &&
            AD5933::setNumberIncrements(NUM_INCR) &&
            AD5933::setPGAGain(PGA_GAIN_X1)))
            {
                Serial.println("FAILED in initialization!");
                while (true) ;
            }
    
      // Perform calibration sweep
      if (AD5933::calibrate(gain, phase, REF_RESIST, NUM_INCR+1))
        Serial.println("Calibrated!");
      else
        Serial.println("Calibration failed...");
    }
    
    void loop(void)
    {
    
      // Complex but more robust method for frequency sweep
      frequencySweepRaw();
    
      // Delay
      delay(5000);
    }
    
    
    void frequencySweepRaw() {
        // Create variables to hold the impedance data and track frequency
        int real, imag, i = 0, cfreq = START_FREQ/1000;
    
        // Initialize the frequency sweep
        if (!(AD5933::setPowerMode(POWER_STANDBY) &&          // place in standby
              AD5933::setControlMode(CTRL_INIT_START_FREQ) && // init start freq
              AD5933::setControlMode(CTRL_START_FREQ_SWEEP))) // begin frequency sweep
             {
                 Serial.println("Could not initialize frequency sweep...");
             }
    
        // Perform the actual sweep
        while ((AD5933::readStatusRegister() & STATUS_SWEEP_DONE) != STATUS_SWEEP_DONE) {
            // Get the frequency data for this frequency point
            if (!AD5933::getComplexData(&real, &imag)) {
                Serial.println("Could not get raw frequency data...");
            }
    
            // Print out the frequency data
            Serial.print(cfreq);
            Serial.print(": R=");
            Serial.print(real);
            Serial.print("/I=");
            Serial.print(imag);
    
            // Compute impedance
            double magnitude = sqrt(pow(real, 2) + pow(imag, 2));
            double impedance = 1/(magnitude*gain[i]);
            Serial.print("  |Z|=");
            Serial.println(impedance);
    
            // Increment the frequency
            i++;
            cfreq += FREQ_INCR/1000;
            AD5933::setControlMode(CTRL_INCREMENT_FREQ);
        }
    
        Serial.println("Frequency sweep complete!");
    
        // Set AD5933 power mode to standby when finished
        if (!AD5933::setPowerMode(POWER_STANDBY))
            Serial.println("Could not set to standby...");
    }

    I think I have a problem calculating the real gain in the circuit and how to take into account the different resistor values in the final gain calculation.

    I would probably also need to incorporate it in the calibration process but since I use a library for the ad5933 I assume I'd have to make my own calibration function?

  • Thanks for sharing the schematic and other information. Until the clipping is fixed there is not much point going further with calibration, etc. The AD5933's built-in "DFT" assumes that it is processing a well-shaped sinewave and there is no way for it to know that the sinewave is distorted, so it crunches it mindlessly and produces erroneous results in the output registers.

    The clipping is probably indicative of instrumentation amplifier getting out of linear mode because the common voltage at its inputs exceeds the range where it can be rejected or the common voltage plus the sinewave p-p voltage makes the instrumentation amplifier clip at a given reference voltage. In the datasheet there are diagrams on Fig. 3 and Fig. 4 showing the outline of the input and output voltage within which the inamp operates linearly. Unfortunately the diagrams are not for your ±10V power and only for Vref = 0, so it will require a bit of an effort figuring out what exactly causing the clipping and how to fix it in this case.

  • So you recvommend checking the inamp in a seperate circuit ?

    Feed it 2.5v ref and and give it a sine wave func input and see if i get the clipping ?

    And what do you say about the fact that across the load I get only 20mv ? Is that legit?

Reply Children
  • across the load I get only 20mv ?

    The voltage across the load is supposed to be controlled by your R_CURRENT resistor: it should be Vexc * R_LOAD / R_CURRENT. Assuming that the Vexc is 2V p-p your R_LOAD is likely 100 times smaller than R_CURRENT giving you 20mV across the former. I would put in a smaller R_CURRENT resistor of, say, 10k instead of 1M, put 10k load between E1 and E2 and check whether the voltage at the output of the U8.1 is about 2V p-p.

    Then check the output of the INA to see if it is is the same 2V p-p there without any clipping and the DC baseline is 2.5V.

  • Thanks

    I'll give a try and I'll update

  • I forgot to mention that on your schematic diagram the inputs of the  U8.1 seem to be flipped: the + input should be connected to Vref, not the "-". Assumed it was a graphics "typo," but could you please double check the actual circuit?

  • yes you're correct , it's a typo, the actual wiring is correct

    I've done some tests yesterday and I discovered that the TL072's slew rate wasn't good enough for my freq range, so now I lowered the freq range and that part worked out

    additionally I've used 1k resistor for the first voltage divider and Ive discovered I have to use larger resistors, otherwise it attenuates the voltage in the first opamp input.

    Finally I've added a 2k resistor as Rg to the inamp to get a stronger signal.

    I still dont get the results I expected, Im going to go over the circuit again now and see where the signal goes wrong

  •  OK  so I checked the circuit and I get a nice sine wave in the amplitude I expect, see figure attached.

    Could you help me out figuring what my total gain should be? I still get wrong readings

    the resistor values I used:

    R_V11=R_V22= 1M

    c= 100nF

    R_current = 10k

    R_protect =1M

    R_V1=R_V2= 1k

    R_IN=2k

    R_FB=1k

  • TL072's slew rate wasn't good enough for my freq range

    Your OPAMPs are operating at/about unity gain and the output is AC 2V p-p, so the estimate for the min slew rate required is 2*Pi*50Khz*1V ≅ 0.3 V/μs, so TL072 should operate OK.

    I've used 1k resistor for the first voltage divider

    Assuming you mean R_V11 and R_22, with the C1 they do produce a high-pass filter with a cut-off frequency of 1 / (2*Pi*(R_V11 || R_22)*C1) . With 10k resistors, as indicated on the diagram, the cut-off would be at about 320 Hz - significantly lower than your operating frequency of 50 KHz. Even with 1k instead of 10k the cut off would be 10 times higher, 3.2 KHz, still considerably lower than 50 KHz to affect your signal much (unless the C1 is also not the 100 nF indicated on the schematic).

    2k resistor as Rg to the inamp

    I would not do that until you get your cricut to work at unity gain with a known resistor load between E1 and E2. It would make sense to lower R_CURRENT to, say, 10k, attach 10k between E1 and E2, make R_IN and RFB resistors equal and see if the same 2V p-p excitation voltage can be found at all OPAMP and INA outputs as well as at the RFB pin of the AD5933. With these values you should not need INA gain. Once everything works as expected it would be time to attach various loads simulating expected practical values between E1 and E2 and change R_CURRENT and INA gain to get reasonable signal into the AD5933 for measuring.

  • R_V11=R_V22= 1M

    c= 100nF

    No point having these two resistors at 1M, much lower should work better. When you send the command to the AD5933 to start outputting the excitation voltage, the high pass filter we discussed earlier takes some time getting to VCC/2: in this case the time constant is (1MΩ ||1MΩ) * 100nF = 50 msec and your code should wait 7-10 times that for the transient to reasonably settle. If your code start measuring the signal before the transient settles, the the AD5933 will be processing "tilted" sinewave with unsettled baseline, so the output will be erroneous.

    what my total gain should be?

    The total gain should be set so that at the highest value of your load impedance, the voltage on the AD5933 RFB pin is about 2V p-p. This way the internal ADC available dynamic range will be mostly utilized and as lower load impedance is measured, the ADC will not be saturating/clipping. As lower and lower impedance is measured the discretization errors from the ADC will start showing in the data, which your circuit can be compensated for by reducing the value of R_CURRENT, adding gain resistor to INA or programming 5x gain into the AD5933 internal PGA or doing all of the above (bringing the ADC input signal back to similar 1-2V p-p, where the discretization error is low). 

  • Thanks ! that helps alot, Ill try all that out

  • Speaking of gain again, in addition to changing R_CURRENT, adding gain resistor to INA and programming 5x gain into the AD5933 there are two more "knobs" to turn: programming different excitation voltages into the chip and changing RFB / R_IN ratio. The latter two resistors turn the AD5933 internal OPAMP into an inverting amplifier with gain equal RFB / R_IN (with the values on your schematics this gain is 0.5, gain of 1 could be more convenient for now).
    To summarize: there is plenty of available gain throughout the circuit from VOUT to RFB along with the ways to change it. The goal is to keep the AC voltage at the ADC input high enough to capture a substantial part of the available dynamic range, but not too high to avoid clipping at the power supply rails.
    Once you get comfortable with gain setting, calibration and measuring various load impedances with the hardware we can get into the details of extracting complex impedance from the chip with the software.

  • Hey would be too much to ask for a quick zoom call ?