Sample MBed program for use with ST XNucleo VL53L1CB board. Uses interrupts to cope with up to 3 sensors in multizone mode. Includes MBed V6.4
Dependencies: X_NUCLEO_53L1A2
main.cpp
- Committer:
- charlesmn
- Date:
- 2021-06-13
- Revision:
- 4:738d308ed16e
- Parent:
- 3:09f23aad108a
File content as of revision 4:738d308ed16e:
/* * This VL53L1CB Expansion board test application performs range measurements * using the onboard embedded sensor and two satellites, in interrupt mode. * Measured ranges are ouput on the Serial Port, running at 115200 baud. * * This is designed to work with MBed v2.x, & MBedOS v5.x / v6.x. * * The Reset button can be used to restart the program. * * *** NOTE : * Default Mbed build system settings disable printf() floating-point support. * Offline builds can enable this, again. * https://github.com/ARMmbed/mbed-os/blob/master/platform/source/minimal-printf/README.md * .\mbed-os\platform\mbed_lib.json * * *** NOTE : By default hardlinks U10, U11, U15 & U18, on the underside of * the X-NUCELO-53L1A2 expansion board are not made/OFF. * These links must be made to allow interrupts from the Satellite boards * to be received. * U11 and U18 must be made/ON to allow interrupts to be received from the * INT_L & INT_R positions; or * U10 and U15 must be made/ON to allow interrupts to be received from the * Alternate INT_L & INT_R positions. * The X_NUCLEO_53L1A2 library defaults to use the INT_L/INT_R positions. * INT_L is available on expansion board Arduino Connector CN5, pin 1 as D8. * Alternate INT_L is on CN5 Connector pin 2 as D9. * INT_R is available on expansion board Arduino Connector CN9, pin 3 as D2. * Alternate INT_R is on CN9 Connector pin 5 as D4. * The pinouts are shown here : https://developer.mbed.org/components/X-NUCLEO-53L1A2/ * */ #include <stdio.h> #include <time.h> #include "mbed.h" #include "XNucleo53L1A2.h" #include "ToF_I2C.h" // define the i2c comms pins #define I2C_SDA D14 #define I2C_SCL D15 #define NUM_SENSORS 3 // define interrupt pins PinName CentreIntPin = A2; // the satellite pins depend on solder blobs on the back of the shield. // they may not exist or may be one of two sets. // the centre pin always exists //PinName LeftIntPin = D8; PinName RightIntPin = D2; // alternate set PinName LeftIntPin = D9; //PinName RightIntPin = D4; static XNucleo53L1A2 *board=NULL; #if (MBED_VERSION > 60300) UnbufferedSerial pc(USBTX, USBRX); extern "C" void wait_ms(int ms); #else Serial pc(SERIAL_TX, SERIAL_RX); #endif #if TARGET_STM // we are cross compiling for an STM32-Nucleo InterruptIn stop_button(BUTTON1); #endif #if TARGET_Freescale // we are cross-compiling for NXP FRDM boards. InterruptIn stop_button(SW2); #endif void process_interrupt( VL53L1CB * sensor,VL53L1_DEV dev ); void print_results( int devSpiNumber, VL53L1_MultiRangingData_t *pMultiRangingData ); VL53L1_Dev_t devCentre; VL53L1_Dev_t devLeft; VL53L1_Dev_t devRight; VL53L1_DEV Dev = &devCentre; /* Installed sensors count */ int sensorCnt = 0; /* installed sensors prefixes */ char installedSensors[3]; /* interrupt requests */ volatile bool centerSensor = false; volatile bool leftSensor = false; volatile bool rightSensor = false; volatile bool int_measuring_stop = false; /* Current sensor number*/ volatile int currentSensor = 0; /* current displayed sensor change IRQ */ volatile bool switchChanged = false; /* ISR callback function of the centre sensor */ void sensor_centre_irq(void) { centerSensor = true; board->sensor_centre->disable_interrupt_measure_detection_irq(); } /* ISR callback function of the left sensor */ void sensor_left_irq(void) { leftSensor = true; board->sensor_left->disable_interrupt_measure_detection_irq(); } /* ISR callback function of the right sensor */ void sensor_right_irq(void) { rightSensor = true; board->sensor_right->disable_interrupt_measure_detection_irq(); } /* ISR callback function of the user blue button to switch measuring sensor. */ void switch_measuring_sensor_irq(void) { stop_button.disable_irq(); switchChanged = true; } /* * This function calls the interrupt handler for each sensor * and outputs the range */ inline void measure_sensors() { int status = 0; bool current = false; uint16_t distance = 0; VL53L1_MultiRangingData_t MultiRangingData; VL53L1_MultiRangingData_t *pMultiRangingData = &MultiRangingData; /* Handle the interrupt and output the range from the centre sensor */ if (centerSensor) { centerSensor = false; status = board->sensor_centre->VL53L1CB_GetDistance(&distance); current = (currentSensor == 0); if (current) { printf("Centre: %d\r\n", distance); } status = board->sensor_centre->VL53L1CB_ClearInterrupt(); board->sensor_centre->enable_interrupt_measure_detection_irq(); } /* Handle the interrupt and output the range from the left sensor */ if (leftSensor) { leftSensor = false; status = board->sensor_left->VL53L1CB_GetDistance(&distance); current = (installedSensors[currentSensor] == 'L'); if (current) { printf("Left: %d\r\n", distance); } status = board->sensor_left->VL53L1CB_ClearInterrupt(); board->sensor_left->enable_interrupt_measure_detection_irq(); } /* Handle the interrupt and output the range from the right sensor */ if (rightSensor) { rightSensor = false; status = board->sensor_right->VL53L1CB_GetDistance(&distance); current = (installedSensors[currentSensor] == 'R'); if (current) { printf("Right: %d\r\n", distance); } status = board->sensor_right->VL53L1CB_ClearInterrupt(); board->sensor_right->enable_interrupt_measure_detection_irq(); } } int configure_sensor(VL53L1CB *Sensor) { int status = 0; // Device Initialization and setting status = Sensor->VL53L1CB_DataInit(); status = Sensor->VL53L1CB_StaticInit(); status = Sensor->VL53L1CB_SetPresetMode( VL53L1_PRESETMODE_MULTIZONES_SCANNING); //configure the regions of interest for each sensor VL53L1_RoiConfig_t roiConfig; roiConfig.NumberOfRoi = 3; roiConfig.UserRois[0].TopLeftX = 0; roiConfig.UserRois[0].TopLeftY = 9; roiConfig.UserRois[0].BotRightX = 4; roiConfig.UserRois[0].BotRightY = 5; roiConfig.UserRois[1].TopLeftX = 5; roiConfig.UserRois[1].TopLeftY = 9; roiConfig.UserRois[1].BotRightX = 9; roiConfig.UserRois[1].BotRightY = 4; roiConfig.UserRois[2].TopLeftX = 11; roiConfig.UserRois[2].TopLeftY = 9; roiConfig.UserRois[2].BotRightX = 15; roiConfig.UserRois[2].BotRightY = 5; status = Sensor->VL53L1CB_SetROI( &roiConfig); status = Sensor->VL53L1CB_SetDistanceMode( VL53L1_DISTANCEMODE_LONG); // status = Sensor->VL53L1_SetMeasurementTimingBudgetMicroSeconds( 100 * 500); // error -21 is because of this. Don't know why return status; } /* * Add to an array a character that represents the sensor and start ranging */ int init_sensors_array() { int status = 0; VL53L1CB *Sensor; uint8_t ToFSensor = 1; // 0=Left, 1=Center(default), 2=Right sensorCnt = 0; if (board->sensor_centre != NULL) { Dev = &devCentre; Dev->i2c_slave_address = NEW_SENSOR_CENTRE_ADDRESS; status = configure_sensor(board->sensor_centre); printf("configuring centre channel \n"); } if (board->sensor_left != NULL) { Dev = &devLeft; Dev->i2c_slave_address = NEW_SENSOR_LEFT_ADDRESS; status = configure_sensor(board->sensor_left); printf("configuring left channel \n"); } if (board->sensor_right != NULL) { Dev = &devRight; Dev->i2c_slave_address = NEW_SENSOR_RIGHT_ADDRESS; status = configure_sensor(board->sensor_right); printf("configuring right channel \n"); } /* start the measure on the center sensor */ if (NULL != board->sensor_centre) { installedSensors[sensorCnt] = 'C'; status = board->sensor_centre->stop_measurement(); if (status != 0) { return status; } status = board->sensor_centre->start_measurement(&sensor_centre_irq); if (status != 0) { return status; } ++sensorCnt; } /* start the measure on the left sensor */ if (NULL != board->sensor_left) { installedSensors[sensorCnt] = 'L'; status = board->sensor_left->stop_measurement(); if (status != 0) { return status; } status = board->sensor_left->start_measurement(&sensor_left_irq); if (status != 0) { return status; } ++sensorCnt; } /* start the measure on the right sensor */ if (NULL != board->sensor_right) { installedSensors[sensorCnt] = 'R'; status = board->sensor_right->stop_measurement(); if (status != 0) { return status; } status = board->sensor_right->start_measurement(&sensor_right_irq); if (status != 0) { return status; } ++sensorCnt; } currentSensor = 0; return status; } /*=================================== Main ================================== =============================================================================*/ int main() { int status; stop_button.rise(&switch_measuring_sensor_irq); stop_button.enable_irq(); pc.baud(115200); // baud rate is important as printf statements take a lot of time printf("mbed version : %d \r\n", MBED_VERSION); // create i2c interface ToF_DevI2C *dev_I2C = new ToF_DevI2C(I2C_SDA, I2C_SCL); /* creates the 53L1A2 expansion board singleton obj */ board = XNucleo53L1A2::instance(dev_I2C, CentreIntPin, LeftIntPin, RightIntPin); printf("board created!\r\n"); /* init the 53L1A1 expansion board with default values */ status = board->init_board(); if (status) { printf("Failed to init board!\r\n"); return status; } printf("board initiated! - %d\r\n", status); /* init an array with chars to id the sensors */ status = init_sensors_array(); if (status != 0) { printf("Failed to init sensors!\r\n"); return status; } printf("loop forever\n"); /* Main ranging interrupt loop */ while (true) { measure_sensors(); if (switchChanged) { ++currentSensor; if (currentSensor == sensorCnt) currentSensor = 0; printf("Sensor changed to %c\r\n", installedSensors[currentSensor]); switchChanged = false; stop_button.enable_irq(); } } } // print out what data is required void print_results( int devNumber, VL53L1_MultiRangingData_t *pMultiRangingData ) { int no_of_object_found=pMultiRangingData->NumberOfObjectsFound; int signal_rate = 0; int ambient_rate = 0; int RoiNumber=pMultiRangingData->RoiNumber; if (( no_of_object_found < 10 ) && ( no_of_object_found != 0)) { for(int j=0; j<no_of_object_found; j++) { if ((pMultiRangingData->RangeData[j].RangeStatus == VL53L1_RANGESTATUS_RANGE_VALID) || (pMultiRangingData->RangeData[j].RangeStatus == VL53L1_RANGESTATUS_RANGE_VALID_NO_WRAP_CHECK_FAIL)) { signal_rate = pMultiRangingData->RangeData[j].SignalRateRtnMegaCps / 65535; ambient_rate = pMultiRangingData->RangeData[j].AmbientRateRtnMegaCps / 65535; printf("\t i2cAddr=%d \t RoiNumber=%d \t status=%d, \t D=%5dmm, \t Signal=%d Mcps, \t Ambient=%d Mcps \n", devNumber, RoiNumber, pMultiRangingData->RangeData[j].RangeStatus, pMultiRangingData->RangeData[j].RangeMilliMeter, signal_rate, ambient_rate); /* // online compiler disables printf() / floating-point support, for code-size reasons. // offline compiler can switch it on. printf("\t i2cAddr=%d \t RoiNumber=%d \t status=%d, \t D=%5dmm, \t Signal=%2.2f Mcps, \t Ambient=%2.2f Mcps \n", devNumber, RoiNumber, pMultiRangingData->RangeData[j].RangeStatus, pMultiRangingData->RangeData[j].RangeMilliMeter, pMultiRangingData->RangeData[j].SignalRateRtnMegaCps / 65535.0, pMultiRangingData->RangeData[j].AmbientRateRtnMegaCps / 65535.0); */ } } } // if (( no_of_object_found < 10 ) && ( no_of_object_found != 0)) } #if (MBED_VERSION > 60300) void wait_ms(int ms) { thread_sleep_for(ms); } #endif