Hello,
We are building a prototype and I am having some trouble getting deterministic results for BCM measurement. We are using the AFE4300 EVM development kit. I have tried calibration and the other methods listed in this forum but nothing seems to work for me.
My application involves collecting I and Q values across all the frequencies.
This is the state machine I use for my calibration. I collect five I and Q values and average them. These I and Q averages are then used to calculate offset and phase.
calibration_result_t afe4300_calibrate(afe4300_t* afe4300, bcm_freq_t freq){ calibration_state_t calib_state = CALIBRATION_CONFIGURE; calibrating = true; calibration_data_t cdata; memset(&cdata, 0, sizeof(calibration_data_t)); calibration_result_t cresult; //LOGD("%d", freq.freq); while(calibrating){ switch(calib_state){ case CALIBRATION_CONFIGURE: write_data(afe4300, ADC_CONTROL_REGISTER, 0x4120, 0, 15); //Differential measurement mode, 32 SPS write_data(afe4300, MISC1_REGISTER, 0x0000, 0, 15); write_data(afe4300, MISC2_REGISTER, 0xFFFF, 0, 15); write_data(afe4300, MISC3_REGISTER, 0x0030, 0, 15); write_data(afe4300, IQ_MODE_ENABLE, 0x0800, 0, 15); //IQ Mode enable write_data(afe4300, WEIGHT_SCALE_CONTROL, 0x0000, 0, 15); write_data(afe4300, ADC_CONTROL_REGISTER_2, 0x0063, 0, 15); //ADC selects output of BCM-I output write_data(afe4300, DEVICE_CONTROL_1, 0x6006, 0, 15); //Power up BCM signal chain set_bcm_dac_freq(afe4300, freq); calib_state = CALIBRATION_RESISTOR_0_SETUP; //LOGD("Configure"); break; case CALIBRATION_RESISTOR_0_SETUP: write_data(afe4300, VSW_MATRIX, 0x0201, 0, 15); //VSENSERN0 - VSENSERP1 write_data(afe4300, ISW_MATRIX, 0x0201, 0, 15); nrf_delay_ms(100); calib_state = CALIBRATION_RESISTOR_0_SAMPLING_I; break; case CALIBRATION_RESISTOR_0_SAMPLING_I: if(data_rdy){ data_rdy = 0; cdata.R0_I_Data[cdata.R0_I_Index++] = get_i_value(afe4300); if(cdata.R0_I_Index == 5){ calib_state = CALIBRATION_RESISTOR_0_SAMPLING_Q; //LOGD("Resistor 0 Sampling I Complete"); } } break; case CALIBRATION_RESISTOR_0_SAMPLING_Q: if(data_rdy){ data_rdy = 0; cdata.R0_Q_Data[cdata.R0_Q_Index++] = get_q_value(afe4300); if(cdata.R0_Q_Index == 5){ calib_state = CALIBRATION_RESISTOR_1_SETUP; } } break; case CALIBRATION_RESISTOR_1_SETUP: write_data(afe4300, VSW_MATRIX, 0x0202, 0, 15); //VSENSERN1 - VSENSERP1 write_data(afe4300, ISW_MATRIX, 0x0202, 0, 15); nrf_delay_ms(100); calib_state = CALIBRATION_RESISTOR_1_SAMPLING_I; break; case CALIBRATION_RESISTOR_1_SAMPLING_I: if(data_rdy){ data_rdy = 0; cdata.R1_I_Data[cdata.R1_I_Index++] = get_i_value(afe4300); if(cdata.R1_I_Index == 5){ calib_state = CALIBRATION_RESISTOR_1_SAMPLING_Q; } } break; case CALIBRATION_RESISTOR_1_SAMPLING_Q: if(data_rdy){ data_rdy = 0; cdata.R1_Q_Data[cdata.R1_Q_Index++] = get_q_value(afe4300); if(cdata.R1_Q_Index == 5){ calib_state = CALIBRATION_CALCULATION; } } break; case CALIBRATION_CALCULATION: ; double R0_I_AVG = (cdata.R0_I_Data[0] + cdata.R0_I_Data[1] + cdata.R0_I_Data[2] + cdata.R0_I_Data[3] + cdata.R0_I_Data[4]) / 5; double R0_Q_AVG = (cdata.R0_Q_Data[0] + cdata.R0_Q_Data[1] + cdata.R0_Q_Data[2] + cdata.R0_Q_Data[3] + cdata.R0_Q_Data[4]) / 5; double R1_I_AVG = (cdata.R1_I_Data[0] + cdata.R1_I_Data[1] + cdata.R1_I_Data[2] + cdata.R1_I_Data[3] + cdata.R1_I_Data[4]) / 5; double R1_Q_AVG = (cdata.R1_Q_Data[0] + cdata.R1_Q_Data[1] + cdata.R1_Q_Data[2] + cdata.R1_Q_Data[3] + cdata.R1_Q_Data[4]) / 5; double MAG_R0 = sqrt( (R0_I_AVG*R0_I_AVG) + (R0_Q_AVG*R0_Q_AVG) ); double MAG_R1 = sqrt( (R1_I_AVG*R1_I_AVG) + (R1_Q_AVG*R1_Q_AVG) ); double slope = (R1_VALUE - R0_VALUE) / (MAG_R1 - MAG_R0); double offset = R0_VALUE - (slope * MAG_R0); double phase = atan( R0_Q_AVG / R0_I_AVG ) * 180 / PI; cresult.offset = offset; cresult.slope = slope; cresult.phase_offset = phase; calibrating = false; LOGD("Slope: %.2f, Offset: %.2f", slope, offset); break; } } return cresult; }
I then use the calculated slope and offset to adjust my measurements.
double MAG = calib_data.slope * sqrt((I_AVG*I_AVG) + (Q_AVG*Q_AVG)) + calib_data.offset; double PHASE = (atan(Q_AVG/I_AVG) * 180 / PI ) + calib_data.phase_offset; double R0 = MAG * sin(MAG*PI/180); double R1 = MAG * cos(MAG*PI/180);
I also added 300ms delays after switching the ADC from I to Q.
What could be the source of this problem? What else do I need to pay attention to?