Post Go back to editing

# Problem in measuring impedance at lower frequency from 10 Hz to 1k Hz using AD5933

Hello everyone, I am developing an impedance measurement system using AD5933 with a microcontroller. I can measure impedance from 47 ohms to several mega ohms from frequency range 5k to 100k Hz. Now I want to measure impedance from frequency range 10 Hz to 4k Hz. I have uploaded my AFE picture. I know there are many threads related to lower frequency excitation, I have gone through them but I did not get an appropriate idea.

I have uploaded a picture below. According to my understanding after going through this table, we can measure impedance at a low-frequencies by simply giving an external clock to AD5933 pin. I have tried but it's just working for 16Mhz and 4Mhz external oscillator clock. For lower frequencies from 10Hz to 1K Hz how can we measure impedance, do we need any calculation for settling cycle register?

Parents
• Quite an elaborate AFE you got there... The suspect would be the circuit R8R9R10C3 that acts as a low-pass filter with a time constant (R8||R9||R10)*C3 = 1.41630901288kOhm*1μF = 1.4 ms, so operating frequencies lower than a few KHz start noticeably leaking through. The suggestion would be to increase the resistors R8, R9, R10 (and, of course, R13 to keep R13/R10 ratio the same) or C3 or all the above. And prepare for long sweep duration.

If your current number of settling cycles works for your measurements at high MCLK, there should be not need to change it at lower MCLK.

• Thank you for your reply, I got this circuit from chabowski paper [1],  In this paper page num. 16 it is discussed that (ICA and ICB are for DC bias canceller. the voltage detectors are averaged on R8 and R9 and its correspond to DC bias voltage.

I think it's not an AFE problem because now I am trying to measure lower frequencies without AFE. I have measured 20kohm resistor with RFB 10kohm, it gives correct measurement from frequency sweep (5k-100k) by using 16Mhz external clock (settling cycle 0x64) and from 1khz to 5khz by using the 4Mhz external clock (settling cycle=0x0F), but when I am connecting 2Mhz external clock it acts as I have shown in video (running infinitely). but if I change the settling cycle from 0x0x0F to 0x05 it gives the result that I have shown in the image (not correct), I have measured 20kohm with 10kohm RFB.

1SIMPLE WIDE FREQUENCY RANGE IMPEDANCE METER BASED ON AD5933 INTEGRATED CIRCUIT

Konrad Chabowski, Tomasz Piasecki, Andrzej Dzierka, Karol Nitsch

Metrology & Measurement System, Vol. XXII (2015), No. 1, pp. 13–24.

• With 10 uF the software should wait 5-7 sec for the circuit to reasonably settle.

I have found one function called "bool AD5933::setSettlingCycles(int time)" in the cpp file of the library. It seems like it can be used to control the settling time cycle. I will look further into it. However, I was wondering how you came out with the 5-7 sec setting time. Is there any formula to calculate the number of settling time cycles required, e.g. the system time constant? Btw I did not change the settling time cycles for any of my test, so I believe it is working on the default now although I have no idea what the default number of settling time cycles is as I could not find it in the datasheet.

If you drill down a bit from here you can see that the failure comes from functions getByte and sendByte, which query the results of Arduino's Wire functions, so, if an error occurs in some byte operation by one of the Wire functions, it is reported as calibration failure.

No wonder I had gotten this error so frequently. Initially I thought it's the problem of the pull up resistor for my I2C bus. Really thanks a lot for pointing this out.

Btw, I have rebuilt the whole system on a breadboard. As you expected, the system works with both the internal and external oscillator (for the latter, the calibration error's gone after I removed the RC filter. Really thanks a lot for your advice). I have experimented on both 47nF and 10uF capacitor as well. The picture below is the comparison between the ideal value and result from evaluation board, breadboard with 47nF cap and breadboard with 10uF cap.

I did not change the default number of settling time cycle (Again, I am still unsure how to modify it using this library. Will check and update). However, I believe that my hardware is working now, with either both 47nF and 10uF cap. I guess that the large gap between the breadboards' results and the evaluation board's results might be due to the connection problem as I used a lot of jumper wires as shown in the picture below.

Will proceed to the rebuild the whole system on a veroboard and see if the error gap is smaller. Please let me know if you have any suggestions to reduce the error gap. Besides, could you share me some refs regarding the "proper calibration" so that I can try out myself first please (Btw I am currently using multipoint calibration)?

Thank you very much.

• I was wondering how you came out with the 5-7 sec setting time.

This was just a guess. The reason is the high-pass filter that is produced by the DC-blocking capacitor and the voltage divider resistors, you have estimated the cut-off frequency at 0.637 Hz. The thing is that in the stand-by mode the VOUT pin of the AD5933 is connected to ground and, once the command to output excitation voltage is received by the chip, VOUT goes to the Vdcoffset and the node voltage where the capacitor is connected to both the divider resistors jumps from Vdd/2 to Vdd/2 + Vdcoffset and slowly goes back down to Vdd/2. As the result, the Vpk sinewave is sitting on the DC baseline that is exponentially sloping down to Vdd/2. The chip does not have any means to check the voltage it mindlessly samples and processes, so if this settling process is not waited out the results coming out of AD5933 are substantially distorted. The time constant for this exponential voltage settling is R*C = 10uF*25k = 0.25s, so for the voltage to settle to 99% it takes 5 times this time constant or1.25s, but to make sure that there is no slope influence on the data it is a good idea to wait at least 7-10 time constants, so 2 -2.5 sec should be sufficient.

it can be used to control the settling time cycle

Number of settling cycles is a different matter - it is wait time between frequency increment and start of the data acquisition at each frequency step in the sweep. What we discussed above happens prior to initiation of the sweep. The DC level in the excitation voltage does not change between the frequency points within the sweep, so this waiting is useful mostly when dealing with resonant circuits, which take time to assume new frequency when excitation changes. The only limitation is that this Number of Settling Cycles cannot be programmed in as zero (from personal experience, this is the undocumented behaviour of the chip)

Will proceed to the rebuild the whole system on a veroboard and see if the error gap is smaller.

I think more work can be done with the breadboards as they are - everything seem to be functional. I would try keeping those two boards as close to each other as possible and have multiple jumper wires between corresponding grounds and Vdd-s to reduce parasitic inductance and would use as short wires as possible along the critical signal pass, specially the node where Rfb meets the Z and "-" input of A2.

Btw I am currently using multipoint calibration

When sweeping wide frequency ranges covering a decade or more, calibrating at every frequency pint is the way to go. Can you tell a bit more as to how you do it with your breadboard setup? Using Arduino library you mentioned? When you do it with the evaluation board - are you using the ADI demo software? It would be useful if you could post the raw Re and Im data in text or CSV format here, it should be possible by using Insert->Image, video, file.

could you share me some refs regarding the "proper calibration"

You might be very well already doing it, hard to tell without knowing your excitation, PGA gain, Rfb, Rcal  value and other parameters. The calibration in official documentation is not clear and aiming at getting absolute value of the impedance under test, which kinda defeats the purpose of the chip capable of measuring complex values. I had a few of calibration discussions in this forum, but after ADI re-designed it, having hard time finding relevant ones, here is one that might help.

• Hi  , thank you for the suggestions. I have spent the last few days replacing all the long jumper wires in my circuit with shorter wires and adding more connections for the ground. The results look better now but still not as good as the evaluation board. I will proceed to modify my code and include the "settling process" before performing frequency sweep.

By the way, I am confused with the "Default" number of settling time cycles, as I could not find it in the datasheet. Do you have any idea regarding this? Besides, may I know if the way of calculating the required number of settling time cycles is also similar to the "settling process" you mentioned above, i.e. calculate the required settling time of the unknown impedance?

When sweeping wide frequency ranges covering a decade or more, calibrating at every frequency pint is the way to go. Can you tell a bit more as to how you do it with your breadboard setup? Using Arduino library you mentioned? When you do it with the evaluation board - are you using the ADI demo software? It would be useful if you could post the raw Re and Im data in text or CSV format here, it should be possible by using Insert->Image, video, file.

In my case, I am trying to measure the impedance of a R||C circuit, where R=1000ohm and C=0.1uF, from 10Hz to 10kHz. This system will be further used for electrochemical biosensor application. I am currently setting up the whole system on breadboards, where all the ICs were soldered on the corresponding DIP adapter following the schematic I shared in the post above. I am not using the ADI demo software and my system is driven using the library I shared before https://github.com/mjmeli/arduino-ad5933 on Arduino IDE with a STM32 Blue Pill microcontroller. As I am sweeping across wide frequency, I have made a few partitions following the recommended MCLKs as shown below:

Desired Results (Derived Mathematically for1000ohm||0.1uF):

 f R I MCLK min|Z| max|Z| RFB_DESIRED RCAL_DESIRED RFB_DESIRED RCAL_DESIRED 10 999.9605 6.282937 25KHz 999.9803 999.9803 1461.763901 998.0319045 1450 950 100 996.0677 62.58478 250kHz 992.1966 998.0319 1453.217265 992.1966154 1450 950 200 984.4541 123.7102 400 940.5874 236.3954 2MHz 314.7234 969.8388 460.9585228 314.7234052 460 300 600 875.563 330.0795 800 798.3 401.2694 1000 716.9568 450.4772 1200 637.5562 480.706 1400 563.7687 495.9169 1600 497.3522 499.993 1800 438.7695 496.2367 2000 387.7266 487.2317 2200 343.5534 474.8942 2400 305.4408 460.5939 2600 272.5731 445.283 2800 244.1938 429.6082 3000 219.6326 413.9977 3200 198.3108 398.7275 3400 179.7363 383.9677 3600 163.4948 369.8165 3800 149.2385 356.3234 4000 136.6765 343.5055 4200 125.5652 331.3586 4400 115.7003 319.8652 4600 106.9103 308.9992 4800 99.05082 298.7302 5000 91.99967 289.0255 16MHz 157.1767 303.3145 230.2083356 157.1767257 230 150 5200 85.65337 279.8515 5400 79.92387 271.1753 5600 74.736 262.9649 5800 70.02536 255.1898 6000 65.73658 247.8211 6200 61.82188 240.8318 6400 58.2399 234.1965 6600 54.95472 227.8919 6800 51.93505 221.8959 7000 49.15352 216.1885 7200 46.58614 210.7507 7400 44.21183 205.5654 7600 42.01198 200.6165 7800 39.97015 195.8891 8000 38.07176 191.3695 8200 36.30385 187.0451 8400 34.65487 182.9041 8600 33.11452 178.9356 8800 31.67355 175.1295 9000 30.32369 171.4764 9200 29.05749 167.9677 9400 27.86825 164.5953 9600 26.74991 161.3516 9800 25.69698 158.2297 10000 24.70452 155.2231

Collected Results:

 Setup Evaluation Board Breadboard with 47nF C_Filter Breadboard with 0.1uF C_Filter f R I R I R I 10 100 200 400 134.16 2.2 223.7 4.76 220.76 86.76 600 933.12 530.76 1009.65 550.84 1039.54 213.06 800 872.92 392.41 970.18 410.91 975.55 290.33 1000 756.63 442.62 867.66 476.63 881.23 430.64 1200 680.98 478.84 776.46 520.44 802.37 488.59 1400 602.19 495.47 682.24 548.4 700.59 517.08 1600 517.68 494.57 594.55 559.91 609.44 543.07 1800 451.97 492.54 521.17 556.25 531.09 543.06 2000 398.4 485.91 457.34 547.21 460.43 540.25 2200 347.62 472.97 396.83 528.27 398.32 524.07 2400 303.37 452.8 346.54 512.43 353.43 511.85 2600 267.57 433.04 305.96 494.71 310.33 493.16 2800 233.93 411.43 271.51 474.01 274.06 475.26 3000 208.28 393.55 242.12 454.29 241.39 454.08 3200 187.37 376.35 217.73 436.17 217.52 434.86 3400 168.69 359.44 195.01 418.02 196.3 416.88 3600 152.42 342.79 178.45 397.25 176.93 400.81 3800 137.79 328.4 162.43 388.38 157.71 385.15 4000 126.4 314.29 146.6 372.07 146 368.61 4200 115.75 301.26 133.79 357.58 132.01 355.73 4400 104.95 285.76 119.74 350.33 122.44 344.94 4600 101.15 273.31 117.46 339.39 111.97 330.09 4800 94.08 263.58 107.79 326.59 104.97 320.4 5000 88.05 254.5 99.15 313.91 98.57 309.71 5200 91.94 287.47 98.01 288.75 91.66 286.25 5400 87.57 278.13 88.54 280.72 88.9 280.44 5600 83.18 270.76 83.15 273.95 83.85 273.83 5800 77.53 264.3 78.73 267.35 77.61 265.53 6000 71.71 256.52 74.27 257.64 72.82 258.76 6200 67.42 248.08 87.56 292.77 68.41 250.44 6400 64.44 240.93 88.2 297.9 66.07 242.88 6600 61.81 235.05 63.36 237.65 62.8 237.09 6800 58.19 229.64 59.47 232.18 59.29 231.62 7000 54.58 223.84 55.24 226.03 54.93 225.91 7200 51.61 217.75 52.4 220.44 52.79 219.33 7400 49.45 211.98 83.22 294.44 50.63 213.89 7600 47.37 207.03 48.31 209.1 48.34 208.89 7800 45.19 202.34 77.17 278.63 46.22 204.03 8000 43.08 197.72 76.47 277.43 44 199.48 8200 41.17 193.02 41.89 194.99 42.44 194.5 8400 39.55 188.64 40.44 190.58 40.96 190.28 8600 38.15 184.64 73.5 268.49 39.32 186.1 8800 36.6 181.06 73.79 269.77 37.94 182.13 9000 34.9 177.07 72.62 267.3 35.57 178.38 9200 33.7 173.37 72.39 265.41 34.87 174.93 9400 32.45 169.82 71.93 263.06 33.73 171.41 9600 31.37 166.54 68.95 253.77 32.47 167.97 9800 30.28 163.38 68.91 252.77 31.43 165.19 10000 29.15 160.37 67.19 247.38 31.2 162.22

You might be very well already doing it, hard to tell without knowing your excitation, PGA gain, Rfb, Rcal  value and other parameters. The calibration in official documentation is not clear and aiming at getting absolute value of the impedance under test, which kinda defeats the purpose of the chip capable of measuring complex values. I had a few of calibration discussions in this forum, but after ADI re-designed it, having hard time finding relevant ones, here is one that might help.

I am using the Range 1 where DC=1.48V and AC=1.98Vpp. As AFE is used in my setup, the DC is rebiased to Vdd/2. My PGA is x1 for all case. The Rfb is calculated based on the formula provided in the tech note as well as our previous discussion in How to correctly calculate the Rfb value in AD5933 . Rcal is simply the Zmin for each partition as you mentioned in other posts that the formula Rcal = 1/3 * (Zmin + Zmax) is not practical. I am not sure about the number of settling cycles used as I still don't understand this part very well. I did not modify it at all so everything about the number of settling cycle remains default. I am only able to sweep down to 400Hz at the moment. Will try to go for lower frequency and update you soon. I will also try to implement the calibration procedures you shared in the link above. Hopefully it can help reduce the error gap between the spectrums collected using my system and the ideal values. Really thank you so much for your help.

• the formula Rcal = 1/3 * (Zmin + Zmax) is not practical

If you are not using demo software, are you controlling the Demo board from your Arduino Blue Pill?

I am confused with the "Default" number of settling time cycles

There is no default number of settling cycles, the demo software defaults it to be 15, but there is no particular reason for that. This is simply the number of excitation voltage sine wave periods the chip outputs after switching to the next frequency in the course of sweep before it starts sampling the Vadc. As long as it is not zero, it should not matter much for your experiments with non-resonant circuits, which most biosensors are. Setting Number of Settling Cycles at 1 should be OK for your measurements and would keep your sweep time short.
If your Z is a resonant circuit, shifting from one frequency to the next causes beating in the current passing through between the resonant frequency ωand the excitation frequency. This beating takes time to pass for the current sine wave at the new excitation frequency no longer be distorted. If the quality factor of Z is Q, the settling time constant can be estimated as τ =2 Q / ω0 and, similarly to the settling we discussed, it is good idea to wait 7-10 times this time constant to make sure the beatings do not affect the measurements.

my system is driven using the library I shared before https://github.com/mjmeli/arduino-ad5933

The AD5933.cpp contains the method "bool AD5933::setSettlingCycles(int time)", but it is not called from the ad5933-test.ino, so this Number of Settling Cycles is not initialised. Datasheet does not specify what value the registers assume upon the chip power-up. When using this library it would make sense to stick with the diagram on Fig. 28, p. 22 of the datasheet, which does require for the Number of Settling Cycles to be initialized.

Collected Results

Big swings in the data at 3-4 points at the lower frequency end are likely from the systematic error from the built-in "DFT" - will require even lower MCLK to eliminate. At the higher frequencies, something is happening at 5KHz, is this the frequency where you are switching from 16MHz to 2MHz MCLK? Not yet clear what it is, but it causes a noticeable step in the data from evaluation board as well as from the setup with two different capacitor values, as if the control binary words for the frequency with the new MCLK are not calculated quite correctly. Could be a number of other issues - we will need to look at it further.
It sounds like you use different Rfb and Rcal for each frequency range (partition), how do you switch Rfb as you sweep across entire frequency range over several partitions? Just to see if the switching between the ranges causes discontinuities in the data, could you connect the Rfb and Rcal you are using above 5KHz (230 and 150 Ohm), perform the entire sweep same way as you did collecting this data and post raw Re and Im values you are getting from the registers? And then the same raw Re and Im values with your R||C network?

the formula Rcal = 1/3 * (Zmin + Zmax) is not practical

Not only it is not practical, it can lead to wrong calibration. For example, if someone is trying to measure an impedance, which does not change much, so that Zmax ≈ Zmin, this formula would suggest to use Rcal = 2/3 * Zmin, which would guarantee the Vadc clipping, faulty calibration and the user endlessly puzzling over incorrect measurement results.

• Hi  ,

If you are not using demo software, are you controlling the Demo board from your Arduino Blue Pill?

Yes, I directly control the demo board via the two small I2C via holes on the board using my Arduino Blue Pill.

If your Z is a resonant circuit, shifting from one frequency to the next causes beating in the current passing through between the resonant frequency ωand the excitation frequency. This beating takes time to pass for the current sine wave at the new excitation frequency no longer be distorted. If the quality factor of Z is Q, the settling time constant can be estimated as τ =2 Q / ω0 and, similarly to the settling we discussed, it is good idea to wait 7-10 times this time constant to make sure the beatings do not affect the measurements.

Yes, my biosensor is actually a resonant circuit. We usually analysed it using Randles Circuit, which can be viewed as R-(R||C). As my current Z unknown is 1000kohm||0.1uF, the time constant τ=RC is 100us and the recommended settling time is 100us * (7 to 10 ) = 0.7ms to 1ms. May I know if this is correct please?

The AD5933.cpp contains the method "bool AD5933::setSettlingCycles(int time)", but it is not called from the ad5933-test.ino, so this Number of Settling Cycles is not initialised. Datasheet does not specify what value the registers assume upon the chip power-up. When using this library it would make sense to stick with the diagram on Fig. 28, p. 22 of the datasheet, which does require for the Number of Settling Cycles to be initialized.

I have figured out why I could directly run frequency sweep without initialising the number of settling cycles. As the number of settling cycles will not be reset automatically, the number I am currently using is the number that I accidentally set when I was testing the commands in the library last time. I have experimented a few numbers and number>60 can give me similar results that I sent you above. When the number is <30, e.g. 15, the measured points aren't even lining on the curve, which I have no idea why. Below is the screenshot of my initialisation:-

where I have modified setStartFrequency and setIncrementFrequency with additional argument CLK so that I can keep changing the MCLK value (ECLK stands for 'external clock').

Big swings in the data at 3-4 points at the lower frequency end are likely from the systematic error from the built-in "DFT" - will require even lower MCLK to eliminate. At the higher frequencies, something is happening at 5KHz, is this the frequency where you are switching from 16MHz to 2MHz MCLK? Not yet clear what it is, but it causes a noticeable step in the data from evaluation board as well as from the setup with two different capacitor values, as if the control binary words for the frequency with the new MCLK are not calculated quite correctly. Could be a number of other issues - we will need to look at it further.

I have tried with MCLK 1MHz. As you expected, I am able to measure down to around 500Hz to 600Hz correctly (which I assume it's correct as it follows the trend). For the discontinuities at the higher frequencies, I believe they are caused by the change of MCLK as well as the calibration resistance. Regarding the calibration method you suggested, I think my method is similar to yours but I calculated the gain factor and system phase directly instead of using the complex gain factor. As my calibration method worked with the demo board before, may I know if it is necessary for me to switch to your method?

Besides, I just realised my start frequency code might be calculated wrongly. Although the results I sent you above may seem to be correct at the moment with my current setup, I only initialised the correct MCLK value in my new setStartFrequency function while doing calibration, but I have forgot to specify the correct MCLK value while performing frequency sweep to my R||C circuit. The oddest part is that after I amended the correct MCLK value in setStartFrequency for my frequency sweep, the results have gone crazy. Something is definitely going wrong in my code. I will check again and get back to you.

It sounds like you use different Rfb and Rcal for each frequency range (partition), how do you switch Rfb as you sweep across entire frequency range over several partitions? Just to see if the switching between the ranges causes discontinuities in the data, could you connect the Rfb and Rcal you are using above 5KHz (230 and 150 Ohm), perform the entire sweep same way as you did collecting this data and post raw Re and Im values you are getting from the registers? And then the same raw Re and Im values with your R||C network?

Actually I plan to automate the Rfb-switching process using a MUX. However, as I am still experimenting on different partitions, I am changing the Rfb and Rcal manually at the moment. Basically, the data I sent you above are the combined version of different measurements instead of an one-shot measurement. Fortunately, I still keep data of each partition before combining as well as their raw Re and Im values from the register. Please see the attached excel file. Thank you.

Besides, may I know if there is any way to calculate the required MCLK for each excitation frequency please? Based on my current results, the table below from the technical note does not seem to be accurate. I am currently trying to measure frequency down to 10Hz, basically the frequency below 500Hz are all wrong although I have changed the MCLK to below 250kHz. The system would even hang when MCLK<250kHz so I am forced to reduce the number of settling cycles, in which the results have become even worse. Would it be the problem of the software bug about the start frequency code I mentioned above? As there are too many uncertainties at the moment, could you give me some advice for debugging please?

As I am sweeping across wide frequency, I have made a few partitions following the recommended MCLKs as shown below:

Thank you so much for your help. I really appreciate it.

• I directly control the demo board via the two small I2C via holes on the board using my Arduino Blue Pill

R-(R||C)

No, it is not resonant, the equivalent circuit would need to contain and inductance and capacitance and the resistance (loss) to be low enough for the Q-factor to be more then 1 to observe any resonant behavior. So, Number of Settling Cycles should not be a factor in your measurements, yet apparently it somehow is - needs further debugging.

I assume it's correct as it follows the trend)

Yes, with complex circuits it is always good idea to check if the collected data follows expected response without jumps or discontinuities.

I calculated the gain factor and system phase directly

Absolutely nothing wrong with it, it is just you need to track two values: gain amplitude and system phase and remember that gain amplitude is multiplicative with the impedance absolute value and system phase is additive to the impedance phase. With complex arithmetic you are dealing with singular complex values and only multiplicative relationship that takes care of amplitude and phase automatically, more compact. Again, no need to switch if complex arithmetic does not look appealing.

the measured points aren't even lining on the curve, which I have no idea why

Likewise, it is really puzzling - the Number of Settling Cycles should not affect your measurements in any significant way. The way the library example you are following initializes the chip, however, is far from optimal. If any of the 7 functions that are called within the logical sum in the If statement fails, the software reports failure, but there is no way to see which of the 7 functions failed specifically. Also, the logical sum does not depend on the order of the terms, so nothing prevents the compiler from calling the functions in the sum in arbitrary order, not necessarily in the order they are in the If statement. If this happens, the initialization order may be wrong, so I would suggest to break this If statement ito 7 individual If statements in the sequence prescribed by the diagram on Fig. 28, p. 22 of the datasheet.
Same applies to the return statement in your code example, returning the logical sum of functions sending the three bytes may or may not keep the byte sequence the same as written in the statement, so it would be safer calling sendByte functions sequentially.
Not that important, but the increment code could be made a bit more accurate by using round():   long freqx = round((increment / (ECLK / 4.0)) * pow(2, 27));

if there is any way to calculate the required MCLK for each excitation frequency please?

At  MCLK 16 MHz the systematic "DSP" error becomes noticeable below 10 KHz, but as "noticeable" it is somewhat subjective, may be down 5 KHz is still OK. This frequency threshold is proportional to MCLK, so if one wants to place this threshold at 10Hz, then MCLK = (10Hz/5KHz) * 16MHz = 32KHz. In reality the "DSP" error is really a function of the Frequency Code rather then the MCLK frequency - that is the reason for reducing MCLK to get accurate data at low frequencies.

The system would even hang when MCLK<250kHz so I am forced to reduce the number of settling cycles,

Not sure if the settling cycles is likely the problem. Some folks in this forum reported the I2C communication becoming unreliable at low MCLK frequencies (although not clear what might be causing it as I2C communication is normally clocked by the SCL from the master) and the remedy was reducing the I2C speed in microcontroller settings.

Would it be the problem of the software bug about the start frequency code

Yes, anything involving frequency codes could cause a problem. Once you have fixed it feel free to post your code via Insert -> </>Code, although remote debugging is typically ineffective.

• XLSX

You have probably noticed that the data from the breadboard is about the same as the data from the Evaluation board about 50% of the time and other 50% - it is off quite substantially. It looks like you are using the same code to collect the data from both boards, but is the microcontroller physically the same or are there two different boards with the same microcontroller type? This could be indicative of I2C communication errors that are not caught by the Arduino Wire functions. Does your breadboard setup have the same pullup resistors 2.2k on SCL and SDA lines as the Evaluation board? Somehow we need to troubleshoot the breadboard setup.

• Hi  , I was using 10kohm pull up resistor initially as I have multiple slxvx (sorry I need to censor the word due to AD "Word Matters") devices on the bus. I am not sure how to calculate the correct pull up resistance when there are multiple slxvx devices on the bus, so I have chosen 10kohm as the safest option. Really thanks a lot for pointing out this problem.

I have changed the pull up resistance back to 2.2kohm and added the 2.5s settling time before frequency sweep (for both calibration and actual measurement). I have also ensured that the modified setStartFrequency() is called correctly with respect to the MCLK used. I can see some improvements in the results as shown below. The frequency sweep from 5kHz to 10kHz is very good, but the gap starts appearing again for 400Hz-5kHz sweep. Besides, I managed to set the settling cycles to 15 (tried with 30, 60 and 255 as well, the results are very consistent) for all my partitions and it did not cause any system hang at all, even when I was scanning down to 10Hz. However, the gap is still very big, and there is no continuation for freq <400Hz. Was wondering if this could be the problem of the breadboard or there is anything I can do to reduce the error?

Besides, please see the attachment below for the newly collected data.

XLSX

I will proceed to separate all the initialisation and sendByte functions, and also use round() for my increment code. Will update soon. Please let me know if there is anything I can do to improve my system.

Really thanks a lot for your help.

• I am not sure how to calculate the correct pull up resistance

Nobody seems to know, the rule of thumb is to start with 10k or 4.7k and go lower if the bus is getting longer and number of devices increases. For some reason your microcontroller seems to like 2.2k installed on the Eval board.
You may ignore the attempts to censor your referring to "slave" devices on the bus - there should be an option to disregard the warning by pushing "Post" button, do you get this "Post" button in the popup dialog?

but the gap starts appearing again

To debug this discontinuity issue, can you just calibrate with the lowest Rfb (230 Ω) while sweeping all the way down to 10 Hz while changing MCLK only between to your partitions, but not the Rfb and Rcal? And then sweep the same way with Rcal or some known resistor R > Rcal and see if there still going to be any discontinuities? And then do the same with your R||C network? And post the Exel here? This should help us to see if the discontinuities are caused by switching between Rfb-s and Rcal-s and not by the software calculating Frequency Codes for different MCLKs incorrectly?  (BTW round() could be used in all Code calculations, not just the increment, although not that important)

XLSX

These are calibration data - all seems to be in order.
The cut-off frequency with C of 0.1 uF is about 64 Hz, which somewhat reduces the effective excitation voltage when you sweep below 100 Hz making measurements slightly suboptimal, but this does not explain the discontinuities and calibration should still lead to correct impedance values.

Another thing is the accuracy of components you are using for calibration and R||C network: the capacitors are known to deviate from their nominal values by up to 10% or more. What are the accuracy of the resistors you are using? It would make sense to try getting some high-precision resistors with 0.1% or better tolerance (avoid the wirewound ones).

I managed to set the settling cycles to 15

It should be safe to try setting this number at 1 to reduce the duration of your sweep, especially at lower end of your spectrum.

• Hi  ,

To debug this discontinuity issue, can you just calibrate with the lowest Rfb (230 Ω) while sweeping all the way down to 10 Hz while changing MCLK only between to your partitions, but not the Rfb and Rcal? And then sweep the same way with Rcal or some known resistor R > Rcal and see if there still going to be any discontinuities?

I have tried with 150ohm, 240ohm and 1kohm||0.1uF from 10Hz to 10kHz with Rfb=230ohm and Rcal=150ohm. I have collected the results twice for each target. Please see the attached excel file for the collected results. For 150ohm, everything seems fine. However, for 240ohm, the error is quite big and the discontinuities are very obvious. For 1kohm||0.1uF, the results are very off for frequency < 600Hz.

XLSX

However, I am not quite sure whether I had performed the frequency sweep correctly as you expected. I basically just combined the partitions together using a for loop so that the data for each partition were collected automatically (previously I would collected the data for each partition first and then combined them together in excel manually). In the beginning of each partition, I have configured the start frequency, num of increments and freq of increment, and also provided a 2.5 settling time. May I know if I have misunderstood what you meant regarding the full sweep?

Or you would actually want me to perform the frequency sweep with only one start frequency and then adjusted the MCLK only when the frequency reaches the threshold (e.g while sweeping from 400Hz to 10kHz, MCLK is changed from 1MHz to 16.776MHz when frequency reaches 5kHz)?

The cut-off frequency with C of 0.1 uF is about 64 Hz, which somewhat reduces the effective excitation voltage when you sweep below 100 Hz making measurements slightly suboptimal, but this does not explain the discontinuities and calibration should still lead to correct impedance values.

I am so sorry. It's a typo in the attached results (Results-20240127). I used 10uF instead of 0.1uF, so the cutoff is actually 0.64Hz. Really sorry about it.

Another thing is the accuracy of components you are using for calibration and R||C network: the capacitors are known to deviate from their nominal values by up to 10% or more. What are the accuracy of the resistors you are using? It would make sense to try getting some high-precision resistors with 0.1% or better tolerance (avoid the wirewound ones).

Noted on this. I have ordered the 0.1% tolerance resistors. Will try it out when I receive them.

It should be safe to try setting this number at 1 to reduce the duration of your sweep, especially at lower end of your spectrum.

I am not sure why but the results were inconsistent when I set it to 1. When the number of settling cycles is 15, the results are very consistent.

Do you think I should try to calibrate the system manually for each partition (as the results I collected before seem quite consistent with the Rfb and Rcal I chose for each partition) and combine them together in a CSV file? I  will then perform a full frequency sweep on my RC based on the calibrated data from CSV file and switch between different values of Rfb using a MUX as proposed in the schematic before. Or Do you think I should continue to debug the system?

• Hi  ,

To debug this discontinuity issue, can you just calibrate with the lowest Rfb (230 Ω) while sweeping all the way down to 10 Hz while changing MCLK only between to your partitions, but not the Rfb and Rcal? And then sweep the same way with Rcal or some known resistor R > Rcal and see if there still going to be any discontinuities?

I have tried with 150ohm, 240ohm and 1kohm||0.1uF from 10Hz to 10kHz with Rfb=230ohm and Rcal=150ohm. I have collected the results twice for each target. Please see the attached excel file for the collected results. For 150ohm, everything seems fine. However, for 240ohm, the error is quite big and the discontinuities are very obvious. For 1kohm||0.1uF, the results are very off for frequency < 600Hz.

XLSX

However, I am not quite sure whether I had performed the frequency sweep correctly as you expected. I basically just combined the partitions together using a for loop so that the data for each partition were collected automatically (previously I would collected the data for each partition first and then combined them together in excel manually). In the beginning of each partition, I have configured the start frequency, num of increments and freq of increment, and also provided a 2.5 settling time. May I know if I have misunderstood what you meant regarding the full sweep?

Or you would actually want me to perform the frequency sweep with only one start frequency and then adjusted the MCLK only when the frequency reaches the threshold (e.g while sweeping from 400Hz to 10kHz, MCLK is changed from 1MHz to 16.776MHz when frequency reaches 5kHz)?

The cut-off frequency with C of 0.1 uF is about 64 Hz, which somewhat reduces the effective excitation voltage when you sweep below 100 Hz making measurements slightly suboptimal, but this does not explain the discontinuities and calibration should still lead to correct impedance values.

I am so sorry. It's a typo in the attached results (Results-20240127). I used 10uF instead of 0.1uF, so the cutoff is actually 0.64Hz. Really sorry about it.

Another thing is the accuracy of components you are using for calibration and R||C network: the capacitors are known to deviate from their nominal values by up to 10% or more. What are the accuracy of the resistors you are using? It would make sense to try getting some high-precision resistors with 0.1% or better tolerance (avoid the wirewound ones).

Noted on this. I have ordered the 0.1% tolerance resistors. Will try it out when I receive them.

It should be safe to try setting this number at 1 to reduce the duration of your sweep, especially at lower end of your spectrum.

I am not sure why but the results were inconsistent when I set it to 1. When the number of settling cycles is 15, the results are very consistent.

Do you think I should try to calibrate the system manually for each partition (as the results I collected before seem quite consistent with the Rfb and Rcal I chose for each partition) and combine them together in a CSV file? I  will then perform a full frequency sweep on my RC based on the calibrated data from CSV file and switch between different values of Rfb using a MUX as proposed in the schematic before. Or Do you think I should continue to debug the system?

Children
• Thanks for posting, very helpful and you did it great. Your system seems to function the way it is supposed to, except with the Rfb = 230 and Rcal = 150 there may be a little bit of clipping present and that likely throws the Z = 240 measurements (when there is no clipping) a bit off - down to 231-232 or so. The suspect is the section in your datasheet, where you estimate Rfb based on Zmin = 150:

 min|Z| max|Z| RFB RCAL RFB_Actual RCAL_Actual 150 150 219.6969697 150 230 150

The formula we discussed earlier calls for Rfb to be less then or equal to the value from the formula, which you calculated at 219.6969697, so it would be safer to pick Rfb of 210 or even 200 to be sure that there is no clipping, the 230 is too risky. It would make sense to repeat this same experiment with lower Rfb and see if the Z = 240 results improve. Something else still could be an issue, later we will probably need to look at the code.

I used 10uF instead of 0.1uF

When the number of settling cycles is 15, the results are very consistent.

Let's keep it this way for now, might need to revisit it once basic functionality is in place. It should not affect the measurements at all, could be something in the code.

• Hi  , I have completed the full measurement (automated each partition with respect to their Rcal and Rfb). First, I collected the calibration data (phases and gain factors with respect to each frequency) based on each partition, and then I stored them as arrays in the code and perform the frequency sweep. Below are the averaged measurements with respect to the partitions and different number of settling cycles

Please see the attached below for more results. I have corrected the Rcal value as well. However, I still have no clue why the errors are still so high. Could you give me any suggestion to debug please? My 0.1% tolerance resistors are arriving soon as well. Will try with them and update soon.
XLSX
Btw, as Rfb is chosen based on Zmin to ensure that the ADC won't saturate and Rcal needs to be > Zmin, may I know if there is anyway to calculate the maximum impedance that a certain combination of Rfb and Rcal can measure accurately with respect to specific sweep frequency? Theoretically, the maximum measurable impedance should be infinite right?

Thank you.

• why the errors are still so high

If the software calculates all frequency codes correctly, you are likely running into the DFT systematic errors. To reduce these errors is it necessary ro reduce MCLK below what you are using for your partitions:
10000 - 5000 Hz  MCLK of 16 MHz is barely OK, lowering it down to 8 MHz would be better
5000 - 400 Hz       MCLK at 640 KHz
400 - 200 Hz         MCLK at 320 KHz
200 - 100 Hz         MCLK at 160 KHz
100 - 10 Hz           MCLK at 16 KHz

I collected the calibration data (phases and gain factors with respect to each frequency) based on each partition, and then I stored them as arrays in the code

Could you please put these calibration data arrays along with the Re(Reg) and Im(Reg) from which you calculated gain and system phase and also the resistor values used as Rfb and Rcal for each and partition(s) in to Excel and post it along with the measurements data?

Theoretically, the maximum measurable impedance should be infinite right?

The maximum theoretical measurable impedance is always infinity as is the case when no Z is connected to the circuit. In practice, if nothing is connected to the circuit, the AD5933 output registers show some fluctuating small values resulting from everpresent electronic noise and interference (typically ±5-10 counts), which, with the calibrated gain, can be formally calculated into a noisy "Zmax" (except on occasions when both registers happen to contain exactly 0), but it is is not all that meaningful.