cool
Dependencies: BLE_API mbed nRF51822
main.cpp
00001 /*---------------------------------------------------------------------------- 00002 LAB EXERCISE - BLE distance 00003 ---------------------------------------- 00004 In this exercise you will write a program which will turn your board into 00005 a BLE distance sensor. You will be able to check the distance with any 00006 device that can read BLE distance readings. 00007 00008 *----------------------------------------------------------------------------*/ 00009 00010 #include "mbed.h" 00011 #include "BLEDevice.h" 00012 #include "DistanceService.h" 00013 00014 #include "vl53l0x_api.h" 00015 #include "vl53l0x_platform.h" 00016 #include "vl53l0x_i2c_platform.h" 00017 00018 // Create an instance of the BLE radio driver, an instance of a Ticker and an instance for the distance sensor 00019 BLEDevice ble; 00020 Ticker blinky; 00021 00022 //SDA: P030 SDCL: P007 addr: ? 00023 00024 // Create three DigitalOut instances for LEDs 00025 DigitalOut led1(LED1); 00026 DigitalOut led2(LED2); 00027 DigitalOut led4(LED4); 00028 00029 // Give your device a name, add the available services to a list and initialize the triggerSensorPolling flag. 00030 const static char DEVICE_NAME[] = "finecoin"; 00031 static const uint16_t uuid16_list[] = {UUID_DISTANCE_SERVICE}; 00032 static volatile bool triggerSensorPolling = false; 00033 00034 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) 00035 { 00036 // When a client device disconnects we need to start advertising again and update the state LEDs. 00037 ble.startAdvertising(); 00038 led2 = 0; 00039 led4 = 1; 00040 } 00041 00042 void connectionCallback(Gap::Handle_t handle_t, Gap::addr_type_t peerAddrType, const Gap::address_t peerAddr, const Gap::ConnectionParams_t * ) 00043 { 00044 // When a connection is established we need to stop advertising and update the state LEDs. 00045 ble.stopAdvertising(); 00046 led2 = 1; 00047 led4 = 0; 00048 } 00049 00050 void onDataWrittenCallback(const GattCharacteristicWriteCBParams *params) {} 00051 00052 void updateValue(void) 00053 { 00054 // Blink a LED every second and set the trigerSensorPolling flag. 00055 led1 = !led1; 00056 triggerSensorPolling = false; 00057 } 00058 00059 00060 /*---------------------------------------------------------------------------- 00061 Sensor 00062 *----------------------------------------------------------------------------*/ 00063 00064 void print_pal_error(VL53L0X_Error Status) 00065 { 00066 char buf[VL53L0X_MAX_STRING_LENGTH]; 00067 VL53L0X_GetPalErrorString(Status, buf); 00068 printf("API Status: %i : %s\n", Status, buf); 00069 } 00070 00071 void print_range_status(VL53L0X_RangingMeasurementData_t* pRangingMeasurementData) 00072 { 00073 char buf[VL53L0X_MAX_STRING_LENGTH]; 00074 uint8_t RangeStatus; 00075 00076 /* 00077 * New Range Status: data is valid when pRangingMeasurementData->RangeStatus = 0 00078 */ 00079 00080 RangeStatus = pRangingMeasurementData->RangeStatus; 00081 00082 VL53L0X_GetRangeStatusString(RangeStatus, buf); 00083 printf("Range Status: %i : %s\n", RangeStatus, buf); 00084 00085 } 00086 00087 VL53L0X_Error WaitMeasurementDataReady(VL53L0X_DEV Dev) 00088 { 00089 VL53L0X_Error Status = VL53L0X_ERROR_NONE; 00090 uint8_t NewDatReady=0; 00091 uint32_t LoopNb; 00092 00093 // Wait until it finished 00094 // use timeout to avoid deadlock 00095 if (Status == VL53L0X_ERROR_NONE) { 00096 LoopNb = 0; 00097 do { 00098 Status = VL53L0X_GetMeasurementDataReady(Dev, &NewDatReady); 00099 if ((NewDatReady == 0x01) || Status != VL53L0X_ERROR_NONE) { 00100 break; 00101 } 00102 LoopNb = LoopNb + 1; 00103 VL53L0X_PollingDelay(Dev); 00104 } while (LoopNb < VL53L0X_DEFAULT_MAX_LOOP); 00105 00106 if (LoopNb >= VL53L0X_DEFAULT_MAX_LOOP) { 00107 Status = VL53L0X_ERROR_TIME_OUT; 00108 } 00109 } 00110 00111 return Status; 00112 } 00113 00114 VL53L0X_Error WaitStopCompleted(VL53L0X_DEV Dev) 00115 { 00116 VL53L0X_Error Status = VL53L0X_ERROR_NONE; 00117 uint32_t StopCompleted=0; 00118 uint32_t LoopNb; 00119 00120 // Wait until it finished 00121 // use timeout to avoid deadlock 00122 if (Status == VL53L0X_ERROR_NONE) { 00123 LoopNb = 0; 00124 do { 00125 Status = VL53L0X_GetStopCompletedStatus(Dev, &StopCompleted); 00126 if ((StopCompleted == 0x00) || Status != VL53L0X_ERROR_NONE) { 00127 break; 00128 } 00129 LoopNb = LoopNb + 1; 00130 VL53L0X_PollingDelay(Dev); 00131 } while (LoopNb < VL53L0X_DEFAULT_MAX_LOOP); 00132 00133 if (LoopNb >= VL53L0X_DEFAULT_MAX_LOOP) { 00134 Status = VL53L0X_ERROR_TIME_OUT; 00135 } 00136 00137 } 00138 00139 return Status; 00140 } 00141 00142 VL53L0X_Dev_t MyDevice; 00143 VL53L0X_Dev_t *pMyDevice = &MyDevice; 00144 00145 void init_sensor() 00146 { 00147 VL53L0X_Error Status = VL53L0X_ERROR_NONE; 00148 VL53L0X_Version_t Version; 00149 VL53L0X_Version_t *pVersion = &Version; 00150 VL53L0X_DeviceInfo_t DeviceInfo; 00151 00152 int32_t status_int; 00153 00154 printf("VL53L0X API Simple Ranging Example\r\n"); 00155 00156 // Initialize Comms 00157 pMyDevice->I2cDevAddr = 0x52; 00158 pMyDevice->comms_type = 1; 00159 pMyDevice->comms_speed_khz = 400; 00160 00161 printf("Init comms\r\n"); 00162 00163 if(Status == VL53L0X_ERROR_NONE) { 00164 status_int = VL53L0X_GetVersion(pVersion); 00165 if (status_int != 0) 00166 Status = VL53L0X_ERROR_CONTROL_INTERFACE; 00167 } 00168 printf("VL53L0X API Version: %d.%d.%d (revision %d)\r\n", pVersion->major, pVersion->minor ,pVersion->build, pVersion->revision); 00169 00170 int addr; 00171 00172 addr = VL53L0X_scan(); 00173 printf("Device found at: %i\r\n", addr); 00174 //uint8_t data; 00175 //data=0; 00176 if(Status == VL53L0X_ERROR_NONE) { 00177 printf ("Call of VL53L0X_DataInit\n"); 00178 uint16_t osc_calibrate_val=0; 00179 Status = VL53L0X_RdWord(&MyDevice, VL53L0X_REG_OSC_CALIBRATE_VAL,&osc_calibrate_val); 00180 printf("%i\n",osc_calibrate_val); 00181 Status = VL53L0X_DataInit(&MyDevice); // Data initialization 00182 print_pal_error(Status); 00183 } 00184 00185 if(Status == VL53L0X_ERROR_NONE) { 00186 Status = VL53L0X_GetDeviceInfo(&MyDevice, &DeviceInfo); 00187 if(Status == VL53L0X_ERROR_NONE) { 00188 printf("VL53L0X_GetDeviceInfo:\n"); 00189 printf("Device Name : %s\n", DeviceInfo.Name); 00190 printf("Device Type : %s\n", DeviceInfo.Type); 00191 printf("Device ID : %s\n", DeviceInfo.ProductId); 00192 printf("ProductRevisionMajor : %d\n", DeviceInfo.ProductRevisionMajor); 00193 printf("ProductRevisionMinor : %d\n", DeviceInfo.ProductRevisionMinor); 00194 00195 if ((DeviceInfo.ProductRevisionMinor != 1) && (DeviceInfo.ProductRevisionMinor != 1)) { 00196 printf("Error expected cut 1.1 but found cut %d.%d\n", 00197 DeviceInfo.ProductRevisionMajor, DeviceInfo.ProductRevisionMinor); 00198 Status = VL53L0X_ERROR_NOT_SUPPORTED; 00199 } 00200 } 00201 print_pal_error(Status); 00202 } 00203 00204 Status = VL53L0X_ERROR_NONE; 00205 uint32_t refSpadCount; 00206 uint8_t isApertureSpads; 00207 uint8_t VhvSettings; 00208 uint8_t PhaseCal; 00209 00210 if(Status == VL53L0X_ERROR_NONE) { 00211 printf ("Call of VL53L0X_StaticInit\n"); 00212 Status = VL53L0X_StaticInit(pMyDevice); // Device Initialization 00213 // StaticInit will set interrupt by default 00214 print_pal_error(Status); 00215 } 00216 00217 if(Status == VL53L0X_ERROR_NONE) { 00218 printf ("Call of VL53L0X_PerformRefCalibration\n"); 00219 Status = VL53L0X_PerformRefCalibration(pMyDevice, 00220 &VhvSettings, &PhaseCal); // Device Initialization 00221 print_pal_error(Status); 00222 } 00223 00224 if(Status == VL53L0X_ERROR_NONE) { 00225 printf ("Call of VL53L0X_PerformRefSpadManagement\n"); 00226 Status = VL53L0X_PerformRefSpadManagement(pMyDevice, 00227 &refSpadCount, &isApertureSpads); // Device Initialization 00228 print_pal_error(Status); 00229 } 00230 00231 if(Status == VL53L0X_ERROR_NONE) { 00232 00233 printf ("Call of VL53L0X_SetDeviceMode\n"); 00234 Status = VL53L0X_SetDeviceMode(pMyDevice, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING); // Setup in single ranging mode 00235 print_pal_error(Status); 00236 } 00237 } 00238 00239 uint32_t take_measurement() 00240 { 00241 VL53L0X_Error Status = VL53L0X_ERROR_NONE; 00242 VL53L0X_RangingMeasurementData_t RangingMeasurementData; 00243 VL53L0X_RangingMeasurementData_t *pRangingMeasurementData = &RangingMeasurementData; 00244 00245 if(Status == VL53L0X_ERROR_NONE) { 00246 printf ("Call of VL53L0X_StartMeasurement\n"); 00247 Status = VL53L0X_StartMeasurement(pMyDevice); 00248 print_pal_error(Status); 00249 } 00250 00251 uint32_t measurement; 00252 if(Status == VL53L0X_ERROR_NONE) { 00253 00254 Status = WaitMeasurementDataReady(pMyDevice); 00255 00256 if(Status == VL53L0X_ERROR_NONE) { 00257 Status = VL53L0X_GetRangingMeasurementData(pMyDevice, pRangingMeasurementData); 00258 00259 measurement = pRangingMeasurementData->RangeMilliMeter; 00260 printf("In loop measurement %lu: %d\n\r", measurement, pRangingMeasurementData->RangeMilliMeter); 00261 00262 // Clear the interrupt 00263 VL53L0X_ClearInterruptMask(pMyDevice, VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY); 00264 VL53L0X_PollingDelay(pMyDevice); 00265 } else { 00266 return -1; 00267 } 00268 } 00269 00270 if(Status == VL53L0X_ERROR_NONE) { 00271 printf ("Call of VL53L0X_StopMeasurement\n"); 00272 Status = VL53L0X_StopMeasurement(pMyDevice); 00273 } 00274 00275 if(Status == VL53L0X_ERROR_NONE) { 00276 printf ("Wait Stop to be competed\n"); 00277 Status = WaitStopCompleted(pMyDevice); 00278 } 00279 00280 if(Status == VL53L0X_ERROR_NONE) 00281 Status = VL53L0X_ClearInterruptMask(pMyDevice, 00282 VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY); 00283 00284 return measurement; 00285 } 00286 00287 /*---------------------------------------------------------------------------- 00288 MAIN function 00289 *----------------------------------------------------------------------------*/ 00290 00291 int main(void){ 00292 //Initialize LEDs (active low) 00293 led1 = 1; 00294 led2 = 0; 00295 led4 = 1; 00296 00297 // Attach the Ticker 00298 blinky.attach(&updateValue, 1); 00299 00300 // Start and reset the BLE radio 00301 ble.init(); 00302 ble.reset(); 00303 00304 // Setup the connection and disconnection callbacks. 00305 ble.onConnection(connectionCallback); 00306 ble.onDisconnection(disconnectionCallback); 00307 00308 // Setup primary service. 00309 DistanceService distanceService = DistanceService(ble, 0); 00310 00311 // Setup advertising. Add BLE-Only flag and advertising data as well as scan response data to the payload 00312 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); 00313 ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)uuid16_list, (uint8_t)sizeof(uuid16_list)); 00314 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); 00315 00316 // Start advertising (make sure you've added all your data first) and set the advertising LED to high 00317 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00318 ble.setAdvertisingInterval(1600); /* 1000ms; in multiples of 0.625ms. */ 00319 00320 ble.startAdvertising(); 00321 00322 init_sensor(); 00323 00324 while(1) { 00325 00326 //If the triggerSensorPolling is set and the device is connected, get the actual distance from the sensor, 00327 //update the characteristic and clean the flag. 00328 00329 if (triggerSensorPolling && led2) { 00330 uint32_t distance = take_measurement(); 00331 distanceService.updateDistance(distance); 00332 triggerSensorPolling = false; 00333 } 00334 00335 ble.waitForEvent(); // Wait for events 00336 } 00337 } 00338 00339 // *******************************ARM University Program Copyright � ARM Ltd 2015*************************************//
Generated on Mon Sep 5 2022 17:19:55 by
1.7.2