First of all let me say that I already posted this question, by mistake, in the 'New users introduction' forum. As I don't know how to move it to another section I decided to start this new thread. In case the administrators consider it necessary I will delete my last post.
That said... I recently purchased an pmodIA board for a project we are conducting at work. The main goal is to obtain some resistivity vs frequency spectra for different objects as part of a object characterization problem involving Oil/Gas stuff.
I am using a Raspberry Pi 3 Model B to control & communicate with the pmodIA. I based my code on those C libraries I mentioned. In order to use i2c protocol with the raspberry pi I use wiringPi library (http://wiringpi.com/reference/i2c-library/).
In my code I have tested everything I've been able to, from all functionalities of the pmod: I get the temperature readings, set the frequency sweep params, make a freq. sweep measurement, etc. I have attached my code to this post (pmodia_test.tar.gz). All functionalities I tested seem to be okay, and everything seems to be working: I get the temperature, I can do a frequency sweep and if I connect the outputs of the pmod to an oscilloscope I can see the frequency sweeping (look at this video I recorded)
Now, the thing is that even though everything seems to be WORKING, the result values I am getting back just make no sense AT ALL!!!
For calibration purposes I am using a 12k resistor. In my code I first set the gain (X1) and range (2Vpp), I configure the sweep params and start it, then I calculate the gainfactor using that 12k resistor (which I later use on all my calculations), and then I ask the user to change the impedance and put the one that they desire to measure.
On the main loop I simply do the frequency sweep, increasing the frequency at each step, calculate the impedance and put this value into an array (Z). I am also using gnuplot to display the results (the values obtained from the pmod are the exact same values that are being plotted using gnuplot, so this is not a display problem, as I checked this).
This is when things get weird. These are the results I got for the following tests:
The following curve is the IMPEDANCE response for the 12k resistor. At low frequencies there are quite a lot of spikes and high values. Notice that this curve is actually pretty close to the 'open circuit' ones from my first question in this post.
The following curve is the MAGNITUDE for that same case.
These spikes are caused by the lower value of Magnitude at low frequencies.
Now, if I zoom to a range from 15kHz and 1MHz you can see that it actually displays something more reasonable (impedance going from 12k to almost 4k).
I repeated the test but now using the 200mVpp output range instead of the 2000mVpp I was using, and the noise appeared back (see following curve).
Am I maybe saturating the ADC or something?
@D@n suggested me to check the part of my code that reads the data, because that noise or those readings might be related to the way I am handling with the signed/unsigned values stored in the ad5933 registers for the real/imaginary data. This is the part of my code that reads those registers:
/******************************************************************************
* @brief Calculate impedance.
*
* @param gainFactor - Gain factor calculated using a known impedance.
*
* @param freqFunction - Select Repeat Frequency Sweep.
*
* @return impedance.
******************************************************************************/double AD5933_CalculateImpedance(double gainFactor,char freqFunction){signedshort realData =0;signedshort imgData =0;double magnitude =0;double impedance =0;int status =0;// Repeat frequency sweep with last set parameters
AD5933_SetRegisterValue(AD5933_REG_CONTROL_HB,
AD5933_CONTROL_FUNCTION(freqFunction)|
AD5933_CONTROL_RANGE(currentRange)|
AD5933_CONTROL_PGA_GAIN(currentGain),1);// Wait for data received to be validwhile((status & AD5933_STAT_DATA_VALID)==0){
status = AD5933_GetRegisterValue(AD5933_REG_STATUS,1);}// Get real and imaginary reg partssignedshortRealPart=0;signedshortImagPart=0;unsignedchar byte =0;int tmp =0;unsignedchar registerAddress = AD5933_REG_REAL_DATA;for(byte =0;byte <2;byte ++){// Read byte from specified registerAddress memory place
tmp = wiringPiI2CReadReg8(i2cdevice,registerAddress);
printf("\t\tReading from Register Address: 0x%02x...0x%02x\n",registerAddress,tmp);// Add this temporal value to our registerValue (remembering that// we are reading bytes that have location value, which means that// each measure we have we not only have to add it to the previous// register value but we also but do a bitwise shift (<< 8) by 1 byteRealPart=RealPart<<8;RealPart+= tmp;// Update value from registerAddress to read next memory position byte
registerAddress = registerAddress +1;}
registerAddress = AD5933_REG_IMAG_DATA;for(byte =0;byte <2;byte ++){// Read byte from specified registerAddress memory place
tmp = wiringPiI2CReadReg8(i2cdevice,registerAddress);
printf("\t\tReading from Register Address: 0x%02x...0x%02x\n",registerAddress,tmp);// Add this temporal value to our registerValue (remembering that// we are reading bytes that have location value, which means that// each measure we have we not only have to add it to the previous// register value but we also but do a bitwise shift (<< 8) by 1 byteImagPart=ImagPart<<8;ImagPart+= tmp;// Update value from registerAddress to read next memory position byte
registerAddress = registerAddress +1;}
magnitude = sqrt((RealPart*RealPart)+(ImagPart*ImagPart));
printf("Z = %hi + %hi*i ... |Z| = %f\n",RealPart,ImagPart,magnitude);return magnitude;}
For those who aren't familiar with the pmodIA, in order to calculate the impedance you have to read the values of 4 registers: 2 of them to read the real part of the measure (0x94 and 0x95) and the other 2 to read the imaginary part of the measure (0x96 and 0x97). These values are signed, as explained in the datasheet. I realized that the original code I got from github stored these values into unsigned short variables and I changed that to signed short. Now the computation of the magnitude ( sqrt(Real² + Imag²) ) seems to be correct, as well as the values read from the registers.
Using this code I can calculate the gainFactor. For the 12k resistor I used, at a frequency of 3 kHz, I get:
I use that gainFactor for all remaining impedance calculations. As an example of how my code seems to be working I copy/pasted the following lines (which are measurements of that 12k resistor at different frequencies). As explained before 0x94 & 0x95 registers contained the SIGNED value of the real part of the magnitude, while 0x96 & 0x97 registers contain the SIGNED value of the imaginary part of the magnitude. So, for instance, If I'm not mistaken, 0xffdf = -33, 0x0015 = 21.
Reading from Register Address: 0x94...0xff
Reading from Register Address: 0x95...0xdf
Reading from Register Address: 0x96...0x00
Reading from Register Address: 0x97...0x15
Z = -33 + 21*i ... |Z| = 39.115214
Impedance read: 3067.859955 ohms (@ 767500 Hz)
Reading from Register Address: 0x94...0xff
Reading from Register Address: 0x95...0xde
Reading from Register Address: 0x96...0x00
Reading from Register Address: 0x97...0x14
Z = -34 + 20*i ... |Z| = 39.446166
Impedance read: 3042.120759 ohms (@ 769000 Hz)
Reading from Register Address: 0x94...0xff
Reading from Register Address: 0x95...0xdb
Reading from Register Address: 0x96...0x00
Reading from Register Address: 0x97...0x11
Z = -37 + 17*i ... |Z| = 40.718546
Impedance read: 2947.060034 ohms (@ 770500 Hz)
Reading from Register Address: 0x94...0xff
Reading from Register Address: 0x95...0xdf
Reading from Register Address: 0x96...0x00
Reading from Register Address: 0x97...0x12
Z = -33 + 18*i ... |Z| = 37.589892
Impedance read: 3192.347538 ohms (@ 772000 Hz)
Reading from Register Address: 0x94...0xff
Reading from Register Address: 0x95...0xde
Reading from Register Address: 0x96...0x00
Reading from Register Address: 0x97...0x12
Z = -34 + 18*i ... |Z| = 38.470768
Impedance read: 3119.251469 ohms (@ 773500 Hz)
Reading from Register Address: 0x94...0xff
Reading from Register Address: 0x95...0xdc
Reading from Register Address: 0x96...0x00
Reading from Register Address: 0x97...0x11
Z = -36 + 17*i ... |Z| = 39.812058
Impedance read: 3014.162156 ohms (@ 775000 Hz)
Reading from Register Address: 0x94...0xff
Reading from Register Address: 0x95...0xde
Reading from Register Address: 0x96...0x00
Reading from Register Address: 0x97...0x10
Z = -34 + 16*i ... |Z| = 37.576588
Extra:
This is what happens when I put SEL to GND (same other conditions, and 12k resistor):
Some extra information: I am supplying 3V3 to the pmodIA through the raspberry pi.
How is it possible that I am getting these results? Is there something wrong with my code? Is my board broken?? Is maybe my settling time for the sweep configuration not right?
Do I have to connect the SEL pin to GND or VCC?
I would really appreciate your help as I need to finish this experiment in, at least, 1 month.
Thank you so much for your attention, and let me know if you need more info.
Question
mbvalentin
Hello to everyone.
First of all let me say that I already posted this question, by mistake, in the 'New users introduction' forum. As I don't know how to move it to another section I decided to start this new thread. In case the administrators consider it necessary I will delete my last post.
That said... I recently purchased an pmodIA board for a project we are conducting at work. The main goal is to obtain some resistivity vs frequency spectra for different objects as part of a object characterization problem involving Oil/Gas stuff.
I already read the guide that digilent guys provide (http://store.digilentinc.com/pmod-ia-impedance-analyzer/) and I found some C libraries for the AD5933 (https://github.com/analogdevicesinc/no-OS/blob/master/Pmods/PmodIA/AD5933.c and https://github.com/analogdevicesinc/no-OS/blob/master/drivers/AD5933/AD5933.c).
I am using a Raspberry Pi 3 Model B to control & communicate with the pmodIA. I based my code on those C libraries I mentioned. In order to use i2c protocol with the raspberry pi I use wiringPi library (http://wiringpi.com/reference/i2c-library/).
In my code I have tested everything I've been able to, from all functionalities of the pmod: I get the temperature readings, set the frequency sweep params, make a freq. sweep measurement, etc. I have attached my code to this post (pmodia_test.tar.gz). All functionalities I tested seem to be okay, and everything seems to be working: I get the temperature, I can do a frequency sweep and if I connect the outputs of the pmod to an oscilloscope I can see the frequency sweeping (look at this video I recorded)
Now, the thing is that even though everything seems to be WORKING, the result values I am getting back just make no sense AT ALL!!!
For calibration purposes I am using a 12k resistor. In my code I first set the gain (X1) and range (2Vpp), I configure the sweep params and start it, then I calculate the gainfactor using that 12k resistor (which I later use on all my calculations), and then I ask the user to change the impedance and put the one that they desire to measure.
On the main loop I simply do the frequency sweep, increasing the frequency at each step, calculate the impedance and put this value into an array (Z). I am also using gnuplot to display the results (the values obtained from the pmod are the exact same values that are being plotted using gnuplot, so this is not a display problem, as I checked this).
This is when things get weird. These are the results I got for the following tests:
The following curve is the IMPEDANCE response for the 12k resistor. At low frequencies there are quite a lot of spikes and high values. Notice that this curve is actually pretty close to the 'open circuit' ones from my first question in this post.
The following curve is the MAGNITUDE for that same case.
These spikes are caused by the lower value of Magnitude at low frequencies.
Now, if I zoom to a range from 15kHz and 1MHz you can see that it actually displays something more reasonable (impedance going from 12k to almost 4k).
I repeated the test but now using the 200mVpp output range instead of the 2000mVpp I was using, and the noise appeared back (see following curve).
Am I maybe saturating the ADC or something?
@D@n suggested me to check the part of my code that reads the data, because that noise or those readings might be related to the way I am handling with the signed/unsigned values stored in the ad5933 registers for the real/imaginary data. This is the part of my code that reads those registers:
For those who aren't familiar with the pmodIA, in order to calculate the impedance you have to read the values of 4 registers: 2 of them to read the real part of the measure (0x94 and 0x95) and the other 2 to read the imaginary part of the measure (0x96 and 0x97). These values are signed, as explained in the datasheet. I realized that the original code I got from github stored these values into unsigned short variables and I changed that to signed short. Now the computation of the magnitude ( sqrt(Real² + Imag²) ) seems to be correct, as well as the values read from the registers.
Using this code I can calculate the gainFactor. For the 12k resistor I used, at a frequency of 3 kHz, I get:
Real = -79
Imag = -35
MAGNITUDE = 86.406021
gainFactor = (1/ (MAGNITUDE * CALIBRATION_IMPEDANCE) ) = (1/(86.406021 * 12000) ) = 9.64439e-7
I use that gainFactor for all remaining impedance calculations. As an example of how my code seems to be working I copy/pasted the following lines (which are measurements of that 12k resistor at different frequencies). As explained before 0x94 & 0x95 registers contained the SIGNED value of the real part of the magnitude, while 0x96 & 0x97 registers contain the SIGNED value of the imaginary part of the magnitude. So, for instance, If I'm not mistaken, 0xffdf = -33, 0x0015 = 21.
Extra:
This is what happens when I put SEL to GND (same other conditions, and 12k resistor):
Some extra information: I am supplying 3V3 to the pmodIA through the raspberry pi.
How is it possible that I am getting these results? Is there something wrong with my code? Is my board broken?? Is maybe my settling time for the sweep configuration not right?
Do I have to connect the SEL pin to GND or VCC?
I would really appreciate your help as I need to finish this experiment in, at least, 1 month.
Thank you so much for your attention, and let me know if you need more info.
Manu B. Valentin
Link to comment
Share on other sites
16 answers to this question
Recommended Posts
Archived
This topic is now archived and is closed to further replies.