void Sample_XTalkCalibrate(void) { VL6180xDev_t myDev; VL6180x_RangeData_t Range; int XTalkRate; int i, status; /* init device */ MyDev_Init(myDev); status = Sample_Init(myDev); if( status <0 ){ HandleError("Sample_Init fail"); } /* run calibration */ XTalkRate = Sample_XTalkRunCalibration(myDev); /*TODO when possible reset re-init device else set back required scaling/filter*/ VL6180x_FilterSetState(myDev, 1); // turn on wrap around filter again VL6180x_UpscaleSetScaling(myDev, 3); // set scaling /* apply cross talk */ status = VL6180x_SetXTalkCompensationRate(myDev, XTalkRate); if( status<0 ){ /* ignore warning but not error */ HandleError("VL6180x_WrWord fail"); } for( i=0; i< 10; i++){ status = VL6180x_RangePollMeasurement(myDev, &Range); MyDev_ShowRange(myDev, Range.range_mm); } }
static int stmvl6180_start(struct stmvl6180_data *data, uint8_t scaling, init_mode_e mode) { int rc = 0; vl6180_dbgmsg("Enter\n"); /* Power up */ rc = data->pmodule_func_tbl->power_up(&data->client_object, &data->reset); if (rc) { vl6180_errmsg("%d,error rc %d\n", __LINE__, rc); return rc; } /* init */ rc = stmvl6180_init_client(data); if (rc) { vl6180_errmsg("%d, error rc %d\n", __LINE__, rc); data->pmodule_func_tbl->power_down(&data->client_object); return -EINVAL; } /* prepare */ VL6180x_Prepare(vl6180x_dev); VL6180x_UpscaleSetScaling(vl6180x_dev, scaling); /* check mode */ if (mode != NORMAL_MODE) { #if VL6180x_WRAP_AROUND_FILTER_SUPPORT /* turn off wrap around filter */ VL6180x_FilterSetState(vl6180x_dev, 0); #endif VL6180x_SetXTalkCompensationRate(vl6180x_dev, 0); VL6180x_UpdateByte(vl6180x_dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_RANGE_ENABLE_MASK, 0); } if (mode == OFFSETCALIB_MODE) VL6180x_SetOffsetCalibrationData(vl6180x_dev, 0); /* start - single shot mode */ VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP|MODE_SINGLESHOT); data->ps_is_singleshot = 1; data->enable_ps_sensor = 1; /* enable work handler */ stmvl6180_schedule_handler(data); vl6180_dbgmsg("End\n"); return rc; }
/** * Implement Xtalk calibration as described in VL6180x Datasheet (DocID026171 Rev 6) * * Device must be initialized * * @note device scaling wrap filter and xtalk setting are scraped ! * It is safer to reset and re init device when done * @warning follow strictly procedure described in the device manual * @param myDev The device * @return The cross talk (9.7 fix point as expected in register) */ int Sample_XTalkRunCalibration(VL6180xDev_t myDev) { VL6180x_RangeData_t Range[N_MEASURE_AVG]; int32_t RangeSum; int32_t RateSum; int status; int i; int XTalkInt; int RealTargetDistance=100; VL6180x_UpscaleSetScaling(myDev, 1); // set scaling x1 // we do not check status as this can fail only in config that do not have configurable upscale #if VL6180x_WRAP_AROUND_FILTER_SUPPORT VL6180x_FilterSetState(myDev, 0); // turn off wrap around filter #endif status = VL6180x_ClearAllInterrupt(myDev); if( status ){ HandleError("VL6180x_ClearAllInterrupt fail"); } /* Ask user to place a black target at know RealTargetDistance (100mm) */ MyDev_UserWait(myDev, "Calibrating : place black target at 100mm from glass"); status=VL6180x_WrWord(myDev, SYSRANGE_CROSSTALK_COMPENSATION_RATE, 0); for( i=0; i<N_MEASURE_AVG; i++){ status = VL6180x_RangePollMeasurement(myDev, &Range[i]); if( status ){ HandleError("VL6180x_RangePollMeasurement fail"); } if( Range[i].errorStatus != 0 ){ HandleError("No target detect"); } } RangeSum=0; RateSum=0; for( i=0; i<N_MEASURE_AVG; i++){ RangeSum+= Range[i].range_mm; RateSum+= Range[i].signalRate_mcps; } /* Rate sum is 9.7 fixpoint so does xtlak computed below * The order of operation is important to have decent final precision without use of floating point * using a higher real distance and number of point may lead to 32 bit integer overflow in formula below */ XTalkInt = RateSum*(N_MEASURE_AVG*RealTargetDistance-RangeSum)/N_MEASURE_AVG /(RealTargetDistance*N_MEASURE_AVG); MyDev_Printf(myDev, "avg range %d rate %d comp=%d\n", RangeSum/N_MEASURE_AVG, RateSum/N_MEASURE_AVG, XTalkInt); return XTalkInt; }