Single Ranging example with High Accuracy for the VL53L0X Time-of-Flight sensor
Dependencies: mbed vl53l0x_api
main.cpp
- Committer:
- adonisduo
- Date:
- 2019-05-03
- Revision:
- 2:98cd8c47c1ad
- Parent:
- 0:b6867e1a23fa
File content as of revision 2:98cd8c47c1ad:
#include "mbed.h" #include "vl53l0x_api.h" #include "vl53l0x_platform.h" #include "vl53l0x_i2c_platform.h" Serial pc(SERIAL_TX, SERIAL_RX); void print_pal_error(VL53L0X_Error Status){ char buf[VL53L0X_MAX_STRING_LENGTH]; VL53L0X_GetPalErrorString(Status, buf); printf("API Status: %i : %s\n", Status, buf); } void print_range_status(VL53L0X_RangingMeasurementData_t* pRangingMeasurementData){ char buf[VL53L0X_MAX_STRING_LENGTH]; uint8_t RangeStatus; /* * New Range Status: data is valid when pRangingMeasurementData->RangeStatus = 0 */ RangeStatus = pRangingMeasurementData->RangeStatus; VL53L0X_GetRangeStatusString(RangeStatus, buf); printf("Range Status: %i : %s\n", RangeStatus, buf); } VL53L0X_Error WaitMeasurementDataReady(VL53L0X_DEV Dev) { VL53L0X_Error Status = VL53L0X_ERROR_NONE; uint8_t NewDatReady=0; uint32_t LoopNb; // Wait until it finished // use timeout to avoid deadlock if (Status == VL53L0X_ERROR_NONE) { LoopNb = 0; do { Status = VL53L0X_GetMeasurementDataReady(Dev, &NewDatReady); if ((NewDatReady == 0x01) || Status != VL53L0X_ERROR_NONE) { break; } LoopNb = LoopNb + 1; VL53L0X_PollingDelay(Dev); } while (LoopNb < VL53L0X_DEFAULT_MAX_LOOP); if (LoopNb >= VL53L0X_DEFAULT_MAX_LOOP) { Status = VL53L0X_ERROR_TIME_OUT; } } return Status; } VL53L0X_Error WaitStopCompleted(VL53L0X_DEV Dev) { VL53L0X_Error Status = VL53L0X_ERROR_NONE; uint32_t StopCompleted=0; uint32_t LoopNb; // Wait until it finished // use timeout to avoid deadlock if (Status == VL53L0X_ERROR_NONE) { LoopNb = 0; do { Status = VL53L0X_GetStopCompletedStatus(Dev, &StopCompleted); if ((StopCompleted == 0x00) || Status != VL53L0X_ERROR_NONE) { break; } LoopNb = LoopNb + 1; VL53L0X_PollingDelay(Dev); } while (LoopNb < VL53L0X_DEFAULT_MAX_LOOP); if (LoopNb >= VL53L0X_DEFAULT_MAX_LOOP) { Status = VL53L0X_ERROR_TIME_OUT; } } return Status; } VL53L0X_Error rangingTest(VL53L0X_Dev_t *pMyDevice) { VL53L0X_Error Status = VL53L0X_ERROR_NONE; VL53L0X_RangingMeasurementData_t RangingMeasurementData; int i; FixPoint1616_t LimitCheckCurrent; uint32_t refSpadCount; uint8_t isApertureSpads; uint8_t VhvSettings; uint8_t PhaseCal; if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_StaticInit\n"); Status = VL53L0X_StaticInit(pMyDevice); // Device Initialization print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_PerformRefCalibration\n"); Status = VL53L0X_PerformRefCalibration(pMyDevice, &VhvSettings, &PhaseCal); // Device Initialization print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) // needed if a coverglass is used and no calibration has been performed { printf ("Call of VL53L0X_PerformRefSpadManagement\n"); Status = VL53L0X_PerformRefSpadManagement(pMyDevice, &refSpadCount, &isApertureSpads); // Device Initialization printf ("refSpadCount = %d, isApertureSpads = %d\n", refSpadCount, isApertureSpads); print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) { // no need to do this when we use VL53L0X_PerformSingleRangingMeasurement printf ("Call of VL53L0X_SetDeviceMode\n"); Status = VL53L0X_SetDeviceMode(pMyDevice, VL53L0X_DEVICEMODE_SINGLE_RANGING); // Setup in single ranging mode print_pal_error(Status); } // Enable/Disable Sigma and Signal check if (Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_SetLimitCheckEnable(pMyDevice, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 1); } if (Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_SetLimitCheckEnable(pMyDevice, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 1); } if (Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_SetLimitCheckValue(pMyDevice, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, (FixPoint1616_t)(0.25*65536)); } if (Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_SetLimitCheckValue(pMyDevice, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, (FixPoint1616_t)(18*65536)); } if (Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_SetMeasurementTimingBudgetMicroSeconds(pMyDevice, 200000); } if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_SetRangeFractionEnable\n"); Status = VL53L0X_SetRangeFractionEnable(pMyDevice, 0x01); } /* * Step 4 : Test ranging mode */ if(Status == VL53L0X_ERROR_NONE) { for(i=0;i<100;i++){ //printf ("Call of VL53L0X_PerformSingleRangingMeasurement\n"); Status = VL53L0X_PerformSingleRangingMeasurement(pMyDevice, &RangingMeasurementData); //print_pal_error(Status); //print_range_status(&RangingMeasurementData); VL53L0X_GetLimitCheckCurrent(pMyDevice, VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, &LimitCheckCurrent); printf("RANGE IGNORE THRESHOLD: %f\n", (float)LimitCheckCurrent/65536.0f); if (Status != VL53L0X_ERROR_NONE) break; //printf("Measured distance: %i\n\n", RangingMeasurementData.RangeMilliMeter); } } return Status; } int main() { VL53L0X_Error Status = VL53L0X_ERROR_NONE; VL53L0X_Dev_t MyDevice; VL53L0X_Dev_t *pMyDevice = &MyDevice; VL53L0X_Version_t Version; VL53L0X_Version_t *pVersion = &Version; VL53L0X_DeviceInfo_t DeviceInfo; int32_t status_int; pc.baud(460800); pc.printf("VL53L0X API Simple Ranging Example\r\n"); // Initialize Comms pMyDevice->I2cDevAddr = 0x52; pMyDevice->comms_type = 1; pMyDevice->comms_speed_khz = 400; pc.printf("Init comms\r\n"); if(Status == VL53L0X_ERROR_NONE) { status_int = VL53L0X_GetVersion(pVersion); if (status_int != 0) Status = VL53L0X_ERROR_CONTROL_INTERFACE; } pc.printf("VL53L0X API Version: %d.%d.%d (revision %d)\r\n", pVersion->major, pVersion->minor ,pVersion->build, pVersion->revision); int addr; addr = VL53L0X_scan(); printf("Device found at: %i\r\n", addr); //uint8_t data; //data=0; if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_DataInit\n"); uint16_t osc_calibrate_val=0; Status = VL53L0X_RdWord(&MyDevice, VL53L0X_REG_OSC_CALIBRATE_VAL,&osc_calibrate_val); printf("%i\n",osc_calibrate_val); Status = VL53L0X_DataInit(&MyDevice); // Data initialization print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_GetDeviceInfo(&MyDevice, &DeviceInfo); if(Status == VL53L0X_ERROR_NONE) { printf("VL53L0X_GetDeviceInfo:\n"); printf("Device Name : %s\n", DeviceInfo.Name); printf("Device Type : %s\n", DeviceInfo.Type); printf("Device ID : %s\n", DeviceInfo.ProductId); printf("ProductRevisionMajor : %d\n", DeviceInfo.ProductRevisionMajor); printf("ProductRevisionMinor : %d\n", DeviceInfo.ProductRevisionMinor); if ((DeviceInfo.ProductRevisionMinor != 1) && (DeviceInfo.ProductRevisionMinor != 1)) { printf("Error expected cut 1.1 but found cut %d.%d\n", DeviceInfo.ProductRevisionMajor, DeviceInfo.ProductRevisionMinor); Status = VL53L0X_ERROR_NOT_SUPPORTED; } } print_pal_error(Status); } VL53L0X_RangingMeasurementData_t RangingMeasurementData; VL53L0X_RangingMeasurementData_t *pRangingMeasurementData = &RangingMeasurementData; Status = VL53L0X_ERROR_NONE; uint32_t refSpadCount; uint8_t isApertureSpads; uint8_t VhvSettings; uint8_t PhaseCal; if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_StaticInit\n"); Status = VL53L0X_StaticInit(pMyDevice); // Device Initialization // StaticInit will set interrupt by default print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_PerformRefCalibration\n"); Status = VL53L0X_PerformRefCalibration(pMyDevice, &VhvSettings, &PhaseCal); // Device Initialization print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_PerformRefSpadManagement\n"); Status = VL53L0X_PerformRefSpadManagement(pMyDevice, &refSpadCount, &isApertureSpads); // Device Initialization print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_SetDeviceMode\n"); Status = VL53L0X_SetDeviceMode(pMyDevice, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING); // Setup in single ranging mode print_pal_error(Status); } if (Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_SetLimitCheckValue(pMyDevice, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, (FixPoint1616_t)(0.25*65536)); print_pal_error(Status); } if (Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_SetLimitCheckValue(pMyDevice, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, (FixPoint1616_t)(16*65536)); print_pal_error(Status); } if (Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_SetMeasurementTimingBudgetMicroSeconds(pMyDevice, 200000); print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_SetRangeFractionEnable\n"); Status = VL53L0X_SetRangeFractionEnable(pMyDevice, 0x01); print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_StartMeasurement\n"); Status = VL53L0X_StartMeasurement(pMyDevice); print_pal_error(Status); } if(Status == VL53L0X_ERROR_NONE) { uint32_t accumulatingNbr = 24; uint32_t measureTimes = 1; uint32_t measurement; uint32_t no_of_measurements = accumulatingNbr * measureTimes; uint16_t* pResults = (uint16_t*)malloc(sizeof(uint16_t) * no_of_measurements); for(measurement=0; measurement<no_of_measurements; measurement++) { Status = WaitMeasurementDataReady(pMyDevice); if(Status == VL53L0X_ERROR_NONE) { Status = VL53L0X_GetRangingMeasurementData(pMyDevice, pRangingMeasurementData); // Status = VL53L0X_PerformSingleRangingMeasurement(pMyDevice, pRangingMeasurementData); *(pResults + measurement) = pRangingMeasurementData->RangeMilliMeter * 100 + pRangingMeasurementData->RangeFractionalPart / 64 * 25; //printf("In loop measurement %lu: %d.%d\n", measurement, pRangingMeasurementData->RangeMilliMeter, pRangingMeasurementData->RangeFractionalPart/64*25); // Clear the interrupt VL53L0X_ClearInterruptMask(pMyDevice, VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY); VL53L0X_PollingDelay(pMyDevice); } else { break; } } if(Status == VL53L0X_ERROR_NONE) { for(int times = 0; times < measureTimes; times++) { float resMeasured = 0; float resAccumulated = 0; float resFiltered = 0; float resMax = 0; float resMin = 0; for(uint16_t aNbr = 0; aNbr < accumulatingNbr ; aNbr++) { resMeasured = *(pResults + aNbr + (uint16_t)(times * (float)accumulatingNbr)); resAccumulated += resMeasured; if(resMeasured > resMax) { resMax = resMeasured; } if(resMeasured < resMin) { resMin = resMeasured; } } resFiltered = (resAccumulated - resMax - resMin) / (accumulatingNbr - 2) / 100; printf("[%3d] %3.3f \n", times, resFiltered); // if (times % 10 == 9) // { // printf("\n"); // } } // for(measurement=0; measurement<no_of_measurements; measurement++) // { // printf("measurement %lu: %d\n", measurement, *(pResults + measurement)); // } } free(pResults); } if(Status == VL53L0X_ERROR_NONE) { printf ("Call of VL53L0X_StopMeasurement\n"); Status = VL53L0X_StopMeasurement(pMyDevice); } if(Status == VL53L0X_ERROR_NONE) { printf ("Wait Stop to be competed\n"); Status = WaitStopCompleted(pMyDevice); } if(Status == VL53L0X_ERROR_NONE) Status = VL53L0X_ClearInterruptMask(pMyDevice, VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY); while (true) if (pc.readable()) { pc.putc(pc.getc()); if(Status == VL53L0X_ERROR_NONE) { Status = rangingTest(pMyDevice); } } }