This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AFE4300: AFE4300 Non-Deterministic Data even after calibration

Part Number: AFE4300

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?