AD5933
Production
The AD5933 is a high precision impedance converter system solution that combines an on-board frequency generator with a 12-bit, 1 MSPS, analog-to-digital...
Datasheet
AD5933 on Analog.com
Hi everyone,
i have a problem when measuring impedance using ad5933 chipset. I connected the ad5933 with the arduino as shown in the picture
I also use the Arduino program from https://github.com/mjmeli/arduino-ad5933
the resistor value i used on sda and scl is 100k as recommended on the datasheet. for rfb i use 100 ohm .
but the measurement results I get are always 100k even though the measured resistor value is different such as 200 ohms etc.
Please could any one can help me out, is more greatful to me.
the resistor value i used on sda and scl is 100k
Usually it should be lower, 10k at most, more often 4.7k or so.
for rfb i use 100 ohm
How about, for starters, using 100k for Rfb instead of 100 Ohm and measuring 200k? The excitation voltage source in the AD5933 is quite far from ideal - it has internal resistance between 200 Ohm and 2.4k depending on the output voltage setting, see Table 17 on p. 30 in the datasheet.
What are the settings you are programming into the chip? Frequency range, excitation voltage, PGA gain and Number of Settling Cycles?
first of all thankyou for your respon. I have changed the resistor value as you suggested but it doesn't work. there are my arduino code, can you help analyze my problem. #include <Wire.h>
#include "AD5933.h"
#define START_FREQ (80000)
#define FREQ_INCR (1000)
#define NUM_INCR (40)
#define REF_RESIST (10000)
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)
{
// Easy to use method for frequency sweep
frequencySweepEasy();
// Delay
delay(5000);
// Complex but more robust method for frequency sweep
frequencySweepRaw();
// Delay
delay(5000);
}
// Easy way to do a frequency sweep. Does an entire frequency sweep at once and
// stores the data into arrays for processing afterwards. This is easy-to-use,
// but doesn't allow you to process data in real time.
void frequencySweepEasy() {
// Create arrays to hold the data
int real[NUM_INCR+1], imag[NUM_INCR+1];
// Perform the frequency sweep
if (AD5933::frequencySweep(real, imag, NUM_INCR+1)) {
// Print the frequency data
int cfreq = START_FREQ/1000;
for (int i = 0; i < NUM_INCR+1; i++, cfreq += FREQ_INCR/1000) {
// Print raw frequency data
Serial.print(cfreq);
Serial.print(": R=");
Serial.print(real[i]);
Serial.print("/I=");
Serial.print(imag[i]);
// Compute impedance
double magnitude = sqrt(pow(real[i], 2) + pow(imag[i], 2));
double impedance = 1/(magnitude*gain[i]);
Serial.print(" |Z|=");
Serial.println(impedance);
}
Serial.println("Frequency sweep complete!");
} else {
Serial.println("Frequency sweep failed...");
}
}
// Removes the frequencySweep abstraction from above. This saves memory and
// allows for data to be processed in real time. However, it's more complex.
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've seen the same question about AD5933 there you suggest to use this arduino code /cfs-file/__key/communityserver-discussions-components-files/318/BIM_5F00_AD5933_2D00_20220503T072902Z_2D00_001.zip I've also tried it and it still doesn't work. I only have 2 weeks left to complete this project I beg your help
Let's stick to the code you used originally. Can you tell what does not work more specifically? When you run your code, does it print anything? If it does, can you post the printout in your message?
the measurement results are always like that even though the resistor value I measured is not 10k. I tried to measure resistors 1k, 5k etc but the output is always 10k like the picture.
It looks like everything is working OK: the program communicates with the functioning chip. The program calibrates gain "assuming" that a 10k resistor is used for calibration as per #define REF_RESIST (10000). So for calibration you need to either connect a physical 10k resistor to your breadboard or some different resistor, but then you need to change the REF_RESIST value to be the same as that different resistor. If you just change the resistor without changing the REF_RESIST in the code to hold the correct value - the program will report any resistor as 10k.
After the program prints "Calibrated!" you need to replace the calibration resistor with a different, "unknown" resistor and the program will perform the sweep and calculate the value of the "unknown" resistor based on calibration performed in the previous step.
sorry i did'nt get it. do i have to always change the value #define_resist before measuring unknown resistor or or the measurement can be done automatically without changing the value
i tried to change the value tu 20k and measuring 20k resistor and yeah i'ts worked. but how to measuring the other resisitor automatically without changing the value of define_resist
do i have to always change the value #define_resist
You only need to change the #define_resist value to match the value of your calibration resistor when you change the calibration resistor. The code calculates the gain factor based on this value. Then you replace the calibration resistor with an "unknown" resistor and the code calculates the value of this resistor using the gain factor obtained in the calibration step.
From the structure of the code you posted, it looks like the code proceeds to measuring immediately after the calibration is done (after it prints "Calibrated!") without giving you time to replace the calibration resistor with the different, "unknown" one, so it measures the calibration resistor as if it where the unknown and reports it (reasonably accurately, BTW).
Perhaps you can add some delay after your code calling calibrate(gain, phase, REF_RESIST, NUM_INCR+1), and calling any of the frequencySweep...() functions, for example, 10-20 seconds: delay(20000) for you to pull the calibration resistor out and put the different, "unknown" resistor in before the sweep starts. Or otherwise pause your code by whatever means convenient, swap the resistors and continue the code's execution.