cool

Dependencies:   BLE_API mbed nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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*************************************//