I am trying to accurately calculate phase of an RC network. From a couple of posts here (including my own) I realized that calibrating the phase offset everytime I use a new frequency might be the easiest thing to do.
I am using an MSP430FR4133 launchpad to control the AFE4300EVM. I got it working for the most part and I can read continuous impedance data from multiple frequencies without any issue (in the IQ mode). However, calculating the phase has been a bit challenging. So my current approach is to initialize all registers, set an initial frequency, set ISW and VSENSE MUX to read from the 100Ohm calibration resistors, read corresponding I and Q, clear ISW and VSENSE MUX, set ISW and VSENSE MUX to read from 750Ohm calibration resistor, increment frequency and repeat. My aim is to 1. Ensure I am able to read 750Ohms properly and 2. Ensure that I can offset whatever phase is already there.
// The command 'miiii?' makes the program enter into frequency sweep mode // iiii is the hex code for the ISW_MUX and VSENSE_MUX // The output takes the format - frequency, I_cali, Q_cali /n frequency,I_calc, Q_calc /n else if (uartRxBuffer[uartRxRdBufPtr] == 'm') { int index = 0; initDRDY(); // Get the output pins for I and V uartRxRdBufPtr++; if (uartRxRdBufPtr >= MAXRXBUF) uartRxRdBufPtr = 0; // Converts the ASCII bytes to Pin address. afe4300outputs = ascii2uint8(uartRxBuffer[uartRxRdBufPtr])<<12; uartRxRdBufPtr++; if (uartRxRdBufPtr >= MAXRXBUF) uartRxRdBufPtr = 0; afe4300outputs |= ascii2uint8(uartRxBuffer[uartRxRdBufPtr])<<8; uartRxRdBufPtr++; if (uartRxRdBufPtr >= MAXRXBUF) uartRxRdBufPtr = 0; afe4300outputs |= ascii2uint8(uartRxBuffer[uartRxRdBufPtr])<<4; uartRxRdBufPtr++; if (uartRxRdBufPtr >= MAXRXBUF) uartRxRdBufPtr = 0; afe4300outputs |= ascii2uint8(uartRxBuffer[uartRxRdBufPtr]); char afeStringData[8]; // Set Initial frequency spiWrite(AFE4300_BCM_DAC_FREQ,0x0000); spiWrite(AFE4300_DEVICE_CONTROL2,0x0000); spiWrite(AFE4300_BCM_DAC_FREQ, frequencies[index]); spiWrite(AFE4300_DEVICE_CONTROL2, frequencies[index+1]); // When 's' is pressed the while loop exits while(UCA0RXBUF != 's'){ // Select Calibration Resistor on PCB - CAL 100 is selected spiWrite(AFE4300_ISW_MUX, 0x0101); spiWrite(AFE4300_VSENSE_MUX, 0x0101); itoa(frequencies[index], &afeStringData[0], 10); uartTXByte(','); // Calibration // Set Peripheral to I spiWrite(AFE4300_ADC_CONTROL_REGISTER2, ADC_REF_SEL_VREF | PERIPHERAL_SEL_BCM_I); while(readADCFlag==0); // Wait till the interrupt readADCFlag = 0; P4OUT ^= BIT0; afe4300Data = spiRead(0); itoa(afe4300Data, &afeStringData[0], 10); uartTXByte(','); // Set Peripheral to Q spiWrite(AFE4300_ADC_CONTROL_REGISTER2, ADC_REF_SEL_VREF | PERIPHERAL_SEL_BCM_Q); while(readADCFlag==0); // Wait till the interrupt readADCFlag = 0; P4OUT ^= BIT0; afe4300Data = spiRead(0); itoa(afe4300Data, afeStringData, 10); uartTXByte('\n'); spiWrite(AFE4300_ISW_MUX, 0x0000); spiWrite(AFE4300_VSENSE_MUX, 0x0000); // Set Pins to required pinout spiWrite(AFE4300_ISW_MUX, afe4300outputs); spiWrite(AFE4300_VSENSE_MUX, afe4300outputs); itoa(frequencies[index], &afeStringData[0], 10); uartTXByte(','); // Calculation // Set Peripheral to I spiWrite(AFE4300_ADC_CONTROL_REGISTER2, ADC_REF_SEL_VREF | PERIPHERAL_SEL_BCM_I); while(readADCFlag==0); // Wait till the interrupt readADCFlag = 0; P4OUT ^= BIT0; afe4300Data = spiRead(0); itoa(afe4300Data, &afeStringData[0], 10); uartTXByte(','); // Set Peripheral to Q spiWrite(AFE4300_ADC_CONTROL_REGISTER2, ADC_REF_SEL_VREF | PERIPHERAL_SEL_BCM_Q); while(readADCFlag==0); // Wait till the interrupt readADCFlag = 0; P4OUT ^= BIT0; afe4300Data = spiRead(0); itoa(afe4300Data, afeStringData, 10); uartTXByte('\n'); index += 2; if (index>8) {index = 0;} // Write New Frequency spiWrite(AFE4300_BCM_DAC_FREQ,0x0000); spiWrite(AFE4300_DEVICE_CONTROL2,0x0000); spiWrite(AFE4300_BCM_DAC_FREQ, frequencies[index]); spiWrite(AFE4300_DEVICE_CONTROL2, frequencies[index+1]); } readADCFlag = 0; DRDYIEL(); uartRxRdBufPtr = 0; uartRxWrBufPtr = 0; uartRxBufLength = 0; } }
When I use this code to collect data, I expected to see the data to fluctuate between what I normally see for 750Ohm and what I normally see for 100Ohm. Instead, the I and Q values are somewhere in between. The only reason I can think of why this would happen is if somehow the resistors are seen in parallel. But the I and Q values are not remotely close to 100Ohms for this to be true. Is there some other register I should program? I am not sure why this code does not work.
Typical I, Q values for 750 Ohm (Z_magnitude is not calibrated, it is calculated as sqrt(I^2 + Q^2), Phase = atan(Q/I))
Frequency, I, Q, Z_magnitude, Phase
8 7424 -3595 8248.624 -25.8381
16 7053 -5756 9103.645 -39.2181
32 7096 -2662 7578.883 -20.5631
64 8522 557 8540.183 3.7395
128 8198 -1405 8317.525 -9.7251
8 7363 -3580 8187.195 -25.9297
16 7041 -5752 9091.82 -39.2464
32 7120 -1438 7263.762 -11.4182
64 8630 1018 8689.835 6.7276
128 8074 2671 8504.335 18.305
Typical I,Q values for 100 Ohm
Frequency, I, Q, Z_magnitude, Phase
8 1049 -415 1128.107 -21.5845
16 994 -875 1324.259 -41.3569
32 1013 -188 1030.298 -10.5138
64 1235 130 1241.823 6.009
128 1137 355 1191.131 17.3397
8 1043 -417 1123.271 -21.7919
16 1045 484 1151.643 24.8516
32 1153 190 1168.55 9.3575
64 1262 186 1275.633 8.3842
Values with switching between two calibration resistors ( Odd rows have values from 100 Ohm resistor (calibration) and Even rows have test values (750 Ohm)).
Frequency, I, Q, Z_magnitude, Phase
8 4350 179 4353.681 2.3564
8 3798 -3733 5325.42 -44.5055
16 4386 -672 4437.182 -8.7108
16 3783 4010 5512.82 46.6685
32 4806 1426 5013.094 16.5263
32 4544 731 4602.423 9.139
64 5693 373 5705.206 3.7486
64 4645 1315 4827.551 15.8068
128 5432 725 5480.169 7.6022
128 3769 2499 4522.208 33.546
8 4369 260 4376.73 3.4057
8 3897 -3439 5197.435 -41.4276
16 4494 -1830 4852.312 -22.1566
16 3332 -5095 6087.795 -56.8163
32 3823 -1848 4246.226 -25.7987
32 4270 -1204 4436.498 -15.7467
64 5499 -181 5501.978 -1.8852
64 4586 1195 4739.137 14.6051
128 5421 697 5465.624 7.3266
128 3765 2474 4505.097 33.3091