ST Expansion SW Team / Mbed OS VL6180_MB63_4sensors_interrupts

Dependencies:   X_NUCLEO_6180

Committer:
charlesmn
Date:
Mon May 03 10:57:15 2021 +0000
Revision:
1:3cef7d50cab4
Parent:
0:e0163b3111e0
Sample program for the VL6180 ToF sensor. Runs up to 4 sensors. Use interrupt mode. MBed V6

Who changed what in which revision?

UserRevisionLine numberNew contents of line
charlesmn 0:e0163b3111e0 1 /**
charlesmn 0:e0163b3111e0 2 ******************************************************************************
charlesmn 0:e0163b3111e0 3 * File Name : main.c
charlesmn 1:3cef7d50cab4 4 * Date : 21/10/2020 09:21:14
charlesmn 0:e0163b3111e0 5 * Description : Main program body
charlesmn 0:e0163b3111e0 6 ******************************************************************************
charlesmn 0:e0163b3111e0 7 *
charlesmn 1:3cef7d50cab4 8 * COPYRIGHT(c) 2020 STMicroelectronics
charlesmn 0:e0163b3111e0 9 *
charlesmn 0:e0163b3111e0 10 * Redistribution and use in source and binary forms, with or without modification,
charlesmn 0:e0163b3111e0 11 * are permitted provided that the following conditions are met:
charlesmn 0:e0163b3111e0 12 * 1. Redistributions of source code must retain the above copyright notice,
charlesmn 0:e0163b3111e0 13 * this list of conditions and the following disclaimer.
charlesmn 0:e0163b3111e0 14 * 2. Redistributions in binary form must reproduce the above copyright notice,
charlesmn 0:e0163b3111e0 15 * this list of conditions and the following disclaimer in the documentation
charlesmn 0:e0163b3111e0 16 * and/or other materials provided with the distribution.
charlesmn 0:e0163b3111e0 17 * 3. Neither the name of STMicroelectronics nor the names of its contributors
charlesmn 0:e0163b3111e0 18 * may be used to endorse or promote products derived from this software
charlesmn 0:e0163b3111e0 19 * without specific prior written permission.
charlesmn 0:e0163b3111e0 20 *
charlesmn 0:e0163b3111e0 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
charlesmn 0:e0163b3111e0 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
charlesmn 0:e0163b3111e0 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
charlesmn 0:e0163b3111e0 24 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
charlesmn 0:e0163b3111e0 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
charlesmn 0:e0163b3111e0 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
charlesmn 0:e0163b3111e0 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
charlesmn 0:e0163b3111e0 28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
charlesmn 0:e0163b3111e0 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
charlesmn 0:e0163b3111e0 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
charlesmn 0:e0163b3111e0 31 *
charlesmn 0:e0163b3111e0 32 ******************************************************************************
charlesmn 0:e0163b3111e0 33
charlesmn 0:e0163b3111e0 34 This program controls VL6180 ToF sensors running on an STM32F401 card with the
charlesmn 0:e0163b3111e0 35 VL6180 shield and up to 3 VL6180 satelite boards. This program works in interrupt
charlesmn 0:e0163b3111e0 36 mode with all 4 VL6180s operating at the same time.
charlesmn 0:e0163b3111e0 37
charlesmn 0:e0163b3111e0 38 Because this program is designed to run on MBed V2 the normal RTOS features
charlesmn 0:e0163b3111e0 39 such as threads and the signalling between them don't exist. Because of this
charlesmn 0:e0163b3111e0 40 the interupt routine signals the main program by setting flags, there is one to
charlesmn 0:e0163b3111e0 41 signal that an interupt has been received from each VL6180. The mainloop then polls
charlesmn 0:e0163b3111e0 42 these flags to know that an interrupt has occured.
charlesmn 0:e0163b3111e0 43
charlesmn 0:e0163b3111e0 44 The display is very crude with no storing of the last digits, each digit is written
charlesmn 0:e0163b3111e0 45 and then a wait occurs and then the next digit is written. Tjis means that a lot of time is
charlesmn 0:e0163b3111e0 46 taken writing tyhe display and any loong period when the display is not serviced
charlesmn 0:e0163b3111e0 47 will cause the display to flicker.
charlesmn 0:e0163b3111e0 48
charlesmn 0:e0163b3111e0 49 In this program access to the VL6180 api is through wrapper functions in
charlesmn 0:e0163b3111e0 50 vl6180_class.cpp. It is also possible to access the api directly. E.G both the lines below
charlesmn 0:e0163b3111e0 51 do the same thing.
charlesmn 0:e0163b3111e0 52
charlesmn 0:e0163b3111e0 53 status = VL6180_ClearInterrupt(dev,INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING);
charlesmn 0:e0163b3111e0 54 status = sensor->vl6180_ClearInterrupt(dev,INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING);
charlesmn 0:e0163b3111e0 55 */
charlesmn 0:e0163b3111e0 56
charlesmn 0:e0163b3111e0 57 /* Includes ------------------------------------------------------------------*/
charlesmn 0:e0163b3111e0 58 #include <stdio.h>
charlesmn 1:3cef7d50cab4 59 #include <string.h>
charlesmn 1:3cef7d50cab4 60 #include <stdlib.h>
charlesmn 1:3cef7d50cab4 61 #include <stdio.h>
charlesmn 0:e0163b3111e0 62
charlesmn 0:e0163b3111e0 63 #include "mbed.h"
charlesmn 0:e0163b3111e0 64 #include "XNucleo6810.h"
charlesmn 0:e0163b3111e0 65 #include <time.h>
charlesmn 0:e0163b3111e0 66
charlesmn 0:e0163b3111e0 67 #include "spi_interface.h"
charlesmn 1:3cef7d50cab4 68 #include "vl6180_api.h"
charlesmn 1:3cef7d50cab4 69 #include "6180a1.h"
charlesmn 0:e0163b3111e0 70
charlesmn 0:e0163b3111e0 71
charlesmn 0:e0163b3111e0 72 //VL6180_SINGLE_DEVICE_DRIVER
charlesmn 0:e0163b3111e0 73
charlesmn 0:e0163b3111e0 74 // i2c tx and rx pins
charlesmn 0:e0163b3111e0 75 #define I2C_SDA D14
charlesmn 0:e0163b3111e0 76 #define I2C_SCL D15
charlesmn 0:e0163b3111e0 77
charlesmn 0:e0163b3111e0 78 #define DigitDisplay_ms 1 /* ms each digit is kept on */
charlesmn 0:e0163b3111e0 79
charlesmn 1:3cef7d50cab4 80 #define NUM_SENSORS 4
charlesmn 1:3cef7d50cab4 81
charlesmn 1:3cef7d50cab4 82 // Define interrupt pins
charlesmn 1:3cef7d50cab4 83 // The interrupt pins depend on solder blobs on the back of the shield.
charlesmn 1:3cef7d50cab4 84 // Each interupt can have two possible pins, this allows all interrupts to be on the same gpio or different gpio
charlesmn 1:3cef7d50cab4 85 // The first values are those an unmodified board has
charlesmn 1:3cef7d50cab4 86 // see ST document UM2657 for more details
charlesmn 1:3cef7d50cab4 87 PinName CentreIntPin = A3;
charlesmn 1:3cef7d50cab4 88 PinName LeftIntPin = D13;
charlesmn 1:3cef7d50cab4 89 PinName RightIntPin = D2;
charlesmn 1:3cef7d50cab4 90 PinName BottomIntPin = A2;
charlesmn 1:3cef7d50cab4 91 // alternate set
charlesmn 1:3cef7d50cab4 92 //PinName CentreIntPin = A5;
charlesmn 1:3cef7d50cab4 93 //PinName LeftIntPin = D8;
charlesmn 1:3cef7d50cab4 94 //PinName RightIntPin = D4;
charlesmn 1:3cef7d50cab4 95 //PinName BottomIntPin = A4;
charlesmn 0:e0163b3111e0 96
charlesmn 0:e0163b3111e0 97
charlesmn 1:3cef7d50cab4 98 // flags that indicate an interrupt has occured
charlesmn 0:e0163b3111e0 99 static int int_centre_result = 0;
charlesmn 0:e0163b3111e0 100 static int int_left_result = 0;
charlesmn 0:e0163b3111e0 101 static int int_right_result = 0;
charlesmn 0:e0163b3111e0 102 static int int_bottom_result = 0;
charlesmn 0:e0163b3111e0 103 static int int_result = 0;
charlesmn 0:e0163b3111e0 104
charlesmn 0:e0163b3111e0 105 void start_sensor(VL6180Dev_t dev ,VL6180 *sensor);
charlesmn 0:e0163b3111e0 106 int get_sensor_data(VL6180Dev_t dev ,VL6180 *sensor);
charlesmn 0:e0163b3111e0 107
charlesmn 0:e0163b3111e0 108
charlesmn 0:e0163b3111e0 109 class WaitForMeasurement {
charlesmn 0:e0163b3111e0 110 public:
charlesmn 0:e0163b3111e0 111
charlesmn 0:e0163b3111e0 112
charlesmn 0:e0163b3111e0 113 // this class services the interrupts from the ToF sensors.
charlesmn 0:e0163b3111e0 114 // There is a limited amount you can do in an interrupt routine; printfs,mutexes break them among other things.
charlesmn 0:e0163b3111e0 115 // We keep things simple by only raising a flag so all the real work is done outside the interrupt.
charlesmn 0:e0163b3111e0 116 // This is designed around MBED V2 which doesn't have the RTOS features that would make this work nicely e.g. semaphores/queues.
charlesmn 0:e0163b3111e0 117 WaitForMeasurement(): _interrupt(A1)
charlesmn 0:e0163b3111e0 118 {
charlesmn 0:e0163b3111e0 119 }
charlesmn 0:e0163b3111e0 120
charlesmn 0:e0163b3111e0 121
charlesmn 0:e0163b3111e0 122 // constructor - Sensor is not used and can be removed
charlesmn 1:3cef7d50cab4 123 WaitForMeasurement(PinName pin,int i2c_address) : _interrupt(pin) // create the InterruptIn on the pin specified to Counter
charlesmn 0:e0163b3111e0 124 {
charlesmn 0:e0163b3111e0 125 int_result = 1;
charlesmn 1:3cef7d50cab4 126 i2c_addr = i2c_address;
charlesmn 0:e0163b3111e0 127 _interrupt.rise(callback(this, &WaitForMeasurement::got_interrupt)); // attach increment function of this counter instance
charlesmn 0:e0163b3111e0 128
charlesmn 0:e0163b3111e0 129 }
charlesmn 0:e0163b3111e0 130
charlesmn 0:e0163b3111e0 131 // function is called every time an interupt is seen. A flag is raised which allows the main routine to service the interupt.
charlesmn 0:e0163b3111e0 132 void got_interrupt()
charlesmn 0:e0163b3111e0 133 {
charlesmn 1:3cef7d50cab4 134 if (i2c_addr == NEW_SENSOR_CENTRE_ADDRESS)
charlesmn 0:e0163b3111e0 135 int_centre_result = 1; //flag to main that interrupt happened
charlesmn 1:3cef7d50cab4 136 if (i2c_addr == NEW_SENSOR_LEFT_ADDRESS)
charlesmn 0:e0163b3111e0 137 int_left_result = 1; //flag to main that interrupt happened
charlesmn 1:3cef7d50cab4 138 if (i2c_addr == NEW_SENSOR_RIGHT_ADDRESS)
charlesmn 0:e0163b3111e0 139 int_right_result = 1; //flag to main that interrupt happened
charlesmn 1:3cef7d50cab4 140 if (i2c_addr == NEW_SENSOR_BOTTOM_ADDRESS)
charlesmn 0:e0163b3111e0 141 int_bottom_result = 1; //flag to main that interrupt happened
charlesmn 1:3cef7d50cab4 142 }
charlesmn 0:e0163b3111e0 143
charlesmn 0:e0163b3111e0 144 //destructor
charlesmn 0:e0163b3111e0 145 ~WaitForMeasurement()
charlesmn 0:e0163b3111e0 146 {
charlesmn 0:e0163b3111e0 147 printf("destruction \n");
charlesmn 0:e0163b3111e0 148 }
charlesmn 0:e0163b3111e0 149
charlesmn 0:e0163b3111e0 150 private:
charlesmn 0:e0163b3111e0 151 InterruptIn _interrupt;
charlesmn 0:e0163b3111e0 152 int status;
charlesmn 1:3cef7d50cab4 153 int i2c_addr;
charlesmn 0:e0163b3111e0 154
charlesmn 0:e0163b3111e0 155 };
charlesmn 0:e0163b3111e0 156
charlesmn 0:e0163b3111e0 157
charlesmn 0:e0163b3111e0 158
charlesmn 0:e0163b3111e0 159
charlesmn 0:e0163b3111e0 160 MyVL6180Dev_t devCentre; //data for each of the vl6180
charlesmn 0:e0163b3111e0 161 MyVL6180Dev_t devLeft;
charlesmn 0:e0163b3111e0 162 MyVL6180Dev_t devRight;
charlesmn 0:e0163b3111e0 163 MyVL6180Dev_t devBottom;
charlesmn 0:e0163b3111e0 164 VL6180Dev_t Dev = &devCentre; // the currently used vl6180
charlesmn 0:e0163b3111e0 165
charlesmn 0:e0163b3111e0 166 volatile int IntrFired=0;
charlesmn 0:e0163b3111e0 167
charlesmn 0:e0163b3111e0 168 VL6180 *Sensor;
charlesmn 0:e0163b3111e0 169
charlesmn 0:e0163b3111e0 170 static XNucleo53L1A1 *board=NULL;
charlesmn 0:e0163b3111e0 171
charlesmn 1:3cef7d50cab4 172 // MBed V6.4 has renamed wait_ms and UnbufferedSerial replaces Serial
charlesmn 1:3cef7d50cab4 173 #if (MBED_VERSION > 60300)
charlesmn 1:3cef7d50cab4 174 UnbufferedSerial pc(SERIAL_TX, SERIAL_RX);
charlesmn 1:3cef7d50cab4 175 extern "C" void wait_ms(int ms);
charlesmn 1:3cef7d50cab4 176 #else
charlesmn 0:e0163b3111e0 177 Serial pc(SERIAL_TX, SERIAL_RX);
charlesmn 1:3cef7d50cab4 178 #endif
charlesmn 0:e0163b3111e0 179
charlesmn 0:e0163b3111e0 180 vl6180_DevI2C *dev_I2C = new vl6180_DevI2C(I2C_SDA, I2C_SCL);
charlesmn 0:e0163b3111e0 181
charlesmn 0:e0163b3111e0 182
charlesmn 1:3cef7d50cab4 183 #define theVL6180Dev 0x52 //the address of a sensor on power up
charlesmn 0:e0163b3111e0 184
charlesmn 0:e0163b3111e0 185 #define i2c_bus (&hi2c1)
charlesmn 0:e0163b3111e0 186 #define def_i2c_time_out 100
charlesmn 0:e0163b3111e0 187
charlesmn 1:3cef7d50cab4 188 static char DISP_CurString[10]; // used to store what is to be displayed on the display
charlesmn 0:e0163b3111e0 189
charlesmn 0:e0163b3111e0 190 VL6180_RangeData_t Range; /* Range measurmeent */
charlesmn 0:e0163b3111e0 191 uint16_t range; /* range average distance */
charlesmn 0:e0163b3111e0 192
charlesmn 0:e0163b3111e0 193
charlesmn 0:e0163b3111e0 194 int main(void)
charlesmn 0:e0163b3111e0 195 {
charlesmn 0:e0163b3111e0 196
charlesmn 0:e0163b3111e0 197 WaitForMeasurement* int1; // the interrupt handler
charlesmn 0:e0163b3111e0 198 WaitForMeasurement* int2; // the interrupt handler
charlesmn 0:e0163b3111e0 199 WaitForMeasurement* int3; // the interrupt handler
charlesmn 0:e0163b3111e0 200 WaitForMeasurement* int4; // the interrupt handler
charlesmn 0:e0163b3111e0 201
charlesmn 0:e0163b3111e0 202 pc.baud(115200); // baud rate is important as printf statements take a lot of time
charlesmn 1:3cef7d50cab4 203
charlesmn 1:3cef7d50cab4 204 printf("Interrupt 4 sensors mbed = %d \r\n",MBED_VERSION);
charlesmn 0:e0163b3111e0 205
charlesmn 0:e0163b3111e0 206 //create I2C channel
charlesmn 0:e0163b3111e0 207 vl6180_DevI2C *dev_I2C = new vl6180_DevI2C(I2C_SDA, I2C_SCL);
charlesmn 0:e0163b3111e0 208
charlesmn 0:e0163b3111e0 209 int status;
charlesmn 0:e0163b3111e0 210
charlesmn 0:e0163b3111e0 211 // create instances for the sensors
charlesmn 1:3cef7d50cab4 212 board = XNucleo53L1A1::instance(dev_I2C, CentreIntPin, LeftIntPin, RightIntPin ,BottomIntPin);
charlesmn 0:e0163b3111e0 213 // find the sensors we have and initialise
charlesmn 0:e0163b3111e0 214 status = board->init_board();
charlesmn 0:e0163b3111e0 215 if (status) {
charlesmn 0:e0163b3111e0 216 printf("Failed to init board!\r\n");
charlesmn 0:e0163b3111e0 217 return 0;
charlesmn 0:e0163b3111e0 218 }
charlesmn 0:e0163b3111e0 219
charlesmn 0:e0163b3111e0 220
charlesmn 0:e0163b3111e0 221 //select centre sensor
charlesmn 0:e0163b3111e0 222 if (board->sensor_centre != NULL ) {
charlesmn 0:e0163b3111e0 223 devCentre.i2c_addr = NEW_SENSOR_CENTRE_ADDRESS;
charlesmn 1:3cef7d50cab4 224 int1 = new WaitForMeasurement(CentreIntPin,NEW_SENSOR_CENTRE_ADDRESS); // create a interrupt class for this interrupt pin
charlesmn 1:3cef7d50cab4 225 start_sensor(&devCentre ,board->sensor_centre);
charlesmn 0:e0163b3111e0 226 }
charlesmn 0:e0163b3111e0 227
charlesmn 0:e0163b3111e0 228 if (board->sensor_left != NULL ) {
charlesmn 0:e0163b3111e0 229 devLeft.i2c_addr = NEW_SENSOR_LEFT_ADDRESS;
charlesmn 1:3cef7d50cab4 230 int2 = new WaitForMeasurement(LeftIntPin,NEW_SENSOR_LEFT_ADDRESS); // create a interrupt class for this interrupt pin
charlesmn 1:3cef7d50cab4 231 start_sensor(&devLeft ,board->sensor_left);
charlesmn 0:e0163b3111e0 232 }
charlesmn 0:e0163b3111e0 233
charlesmn 0:e0163b3111e0 234 if (board->sensor_right != NULL ) {
charlesmn 0:e0163b3111e0 235 devRight.i2c_addr = NEW_SENSOR_RIGHT_ADDRESS;
charlesmn 1:3cef7d50cab4 236 int2 = new WaitForMeasurement(RightIntPin,NEW_SENSOR_RIGHT_ADDRESS); // create a interrupt class for this interrupt pin
charlesmn 1:3cef7d50cab4 237 start_sensor(&devRight ,board->sensor_right);
charlesmn 0:e0163b3111e0 238 }
charlesmn 0:e0163b3111e0 239
charlesmn 1:3cef7d50cab4 240 if (board->sensor_bottom != NULL ) {
charlesmn 0:e0163b3111e0 241 devBottom.i2c_addr = NEW_SENSOR_BOTTOM_ADDRESS;
charlesmn 1:3cef7d50cab4 242 int2 = new WaitForMeasurement(BottomIntPin,NEW_SENSOR_BOTTOM_ADDRESS); // create a interrupt class for this interrupt pin
charlesmn 1:3cef7d50cab4 243 start_sensor(&devBottom ,board->sensor_bottom);
charlesmn 0:e0163b3111e0 244 }
charlesmn 0:e0163b3111e0 245
charlesmn 0:e0163b3111e0 246
charlesmn 0:e0163b3111e0 247
charlesmn 0:e0163b3111e0 248 /* Infinite loop */
charlesmn 0:e0163b3111e0 249 while (1) {
charlesmn 1:3cef7d50cab4 250
charlesmn 1:3cef7d50cab4 251 // process interrupts
charlesmn 0:e0163b3111e0 252 if ( int_centre_result == 1 )
charlesmn 0:e0163b3111e0 253 {
charlesmn 0:e0163b3111e0 254 int_centre_result = 0; //clear interrupt flag
charlesmn 0:e0163b3111e0 255 Dev = &devCentre;
charlesmn 0:e0163b3111e0 256 Sensor=board->sensor_centre;
charlesmn 0:e0163b3111e0 257
charlesmn 0:e0163b3111e0 258 int result = get_sensor_data(Dev , Sensor);
charlesmn 0:e0163b3111e0 259 if ( result != 0)
charlesmn 0:e0163b3111e0 260 printf("C %d \n",result);
charlesmn 0:e0163b3111e0 261 }
charlesmn 0:e0163b3111e0 262
charlesmn 0:e0163b3111e0 263 if ( int_left_result == 1 )
charlesmn 0:e0163b3111e0 264 {
charlesmn 0:e0163b3111e0 265 int_left_result = 0; //clear interrupt flag
charlesmn 0:e0163b3111e0 266 Dev = &devLeft;
charlesmn 0:e0163b3111e0 267 Sensor=board->sensor_left;
charlesmn 0:e0163b3111e0 268
charlesmn 0:e0163b3111e0 269 int result = get_sensor_data(Dev , Sensor);
charlesmn 0:e0163b3111e0 270 if ( result != 0)
charlesmn 0:e0163b3111e0 271 printf("L %d \n",result);
charlesmn 0:e0163b3111e0 272 }
charlesmn 0:e0163b3111e0 273
charlesmn 0:e0163b3111e0 274 if ( int_right_result == 1 )
charlesmn 0:e0163b3111e0 275 {
charlesmn 0:e0163b3111e0 276 int_right_result = 0; //clear interrupt flag
charlesmn 0:e0163b3111e0 277 Dev = &devRight;
charlesmn 0:e0163b3111e0 278 Sensor=board->sensor_right;
charlesmn 0:e0163b3111e0 279
charlesmn 0:e0163b3111e0 280 int result = get_sensor_data(Dev , Sensor);
charlesmn 0:e0163b3111e0 281 if ( result != 0)
charlesmn 0:e0163b3111e0 282 printf("R %d \n",result);
charlesmn 0:e0163b3111e0 283 }
charlesmn 0:e0163b3111e0 284
charlesmn 0:e0163b3111e0 285 if ( int_bottom_result == 1 )
charlesmn 0:e0163b3111e0 286 {
charlesmn 0:e0163b3111e0 287 int_bottom_result = 0; //clear interrupt flag
charlesmn 0:e0163b3111e0 288 Dev = &devBottom;
charlesmn 0:e0163b3111e0 289 Sensor=board->sensor_bottom;
charlesmn 0:e0163b3111e0 290
charlesmn 0:e0163b3111e0 291 int result = get_sensor_data(Dev , Sensor);
charlesmn 0:e0163b3111e0 292 if ( result != 0)
charlesmn 0:e0163b3111e0 293 printf("B %d \n",result);
charlesmn 0:e0163b3111e0 294 }
charlesmn 0:e0163b3111e0 295
charlesmn 0:e0163b3111e0 296
charlesmn 0:e0163b3111e0 297 // the display is very simple and requires written to frequently so
charlesmn 0:e0163b3111e0 298 // we are writing to the display when we would normally sleep.
charlesmn 0:e0163b3111e0 299 // when we are not writing to the display it is blank
charlesmn 0:e0163b3111e0 300 {
charlesmn 0:e0163b3111e0 301 for (int i = 0 ;i < 10;i++)
charlesmn 0:e0163b3111e0 302 { // write to display
charlesmn 0:e0163b3111e0 303 XNUCLEO6180XA1_DisplayString(DISP_CurString, DigitDisplay_ms* 5);
charlesmn 0:e0163b3111e0 304 }
charlesmn 0:e0163b3111e0 305 }
charlesmn 0:e0163b3111e0 306
charlesmn 0:e0163b3111e0 307 }
charlesmn 0:e0163b3111e0 308 }
charlesmn 0:e0163b3111e0 309
charlesmn 0:e0163b3111e0 310
charlesmn 1:3cef7d50cab4 311 // start a sensor
charlesmn 0:e0163b3111e0 312 void start_sensor(VL6180Dev_t dev ,VL6180 *sensor)
charlesmn 0:e0163b3111e0 313 {
charlesmn 0:e0163b3111e0 314
charlesmn 0:e0163b3111e0 315 /* Note that if we waited 1msec we could bypass VL6180_WaitDeviceBooted(&Dev); */
charlesmn 0:e0163b3111e0 316 int status;
charlesmn 0:e0163b3111e0 317 status = sensor->vl6180_WaitDeviceBooted(dev);
charlesmn 0:e0163b3111e0 318 printf("vl6180_WaitDeviceBooted %d %d\n",status, dev->i2c_addr);
charlesmn 0:e0163b3111e0 319 status = sensor->vl6180_InitData(dev);
charlesmn 0:e0163b3111e0 320 printf("vl6180_InitData %d %d\n",status, dev->i2c_addr);
charlesmn 0:e0163b3111e0 321
charlesmn 0:e0163b3111e0 322 status = sensor->vl6180_FilterSetState(dev,0); // disbale as not effective in continuous mose
charlesmn 0:e0163b3111e0 323 printf("vl6180_FilterSetState %d \n",status);
charlesmn 0:e0163b3111e0 324 status = sensor->vl6180_Prepare(dev); // sensor init
charlesmn 0:e0163b3111e0 325 printf("vl6180_Prepare %d \n",status);
charlesmn 0:e0163b3111e0 326
charlesmn 0:e0163b3111e0 327 status = sensor->vl6180_UpscaleSetScaling(dev, 2); // set scaling by 2 to get ranging in range 0 to 400mm
charlesmn 0:e0163b3111e0 328 printf("vl6180_UpscaleSetScaling %d \n",status);
charlesmn 0:e0163b3111e0 329
charlesmn 0:e0163b3111e0 330 // if slow reaction is enough then set a high time like 100 ms (up to 2550 msec)
charlesmn 0:e0163b3111e0 331 // if fastest reaction is required then set 0 that will set minimal possible
charlesmn 0:e0163b3111e0 332 status = sensor->vl6180_RangeSetInterMeasPeriod(dev, 100);
charlesmn 0:e0163b3111e0 333 printf("vl6180_RangeSetInterMeasPeriod %d \n",status);
charlesmn 0:e0163b3111e0 334 // set vl6180x gpio1 pin to range interrupt output with high polarity (rising edge)
charlesmn 0:e0163b3111e0 335 status = sensor->vl6180_SetupGPIO1(dev, GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT, INTR_POL_HIGH);
charlesmn 0:e0163b3111e0 336 printf("vl6180_SetupGPIO1 %d \n",status);
charlesmn 0:e0163b3111e0 337 // set range interrupt reporting to low threshold
charlesmn 0:e0163b3111e0 338 status = sensor->vl6180_RangeConfigInterrupt(dev, CONFIG_GPIO_INTERRUPT_LEVEL_LOW);
charlesmn 0:e0163b3111e0 339 printf("vl6180_RangeConfigInterrupt %d \n",status);
charlesmn 0:e0163b3111e0 340 // we don't care of high threshold as we don't use it , group hold is managed externaly
charlesmn 0:e0163b3111e0 341 status = sensor->vl6180_RangeSetThresholds(dev, 100, 00, 0);
charlesmn 0:e0163b3111e0 342 printf("vl6180_RangeSetThresholds %d %d\n",status, dev->i2c_addr);
charlesmn 0:e0163b3111e0 343
charlesmn 0:e0163b3111e0 344 status = sensor->vl6180_ClearInterrupt(dev,INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING);
charlesmn 0:e0163b3111e0 345 printf("vl6180_ClearInterrupt %d \n",status);
charlesmn 0:e0163b3111e0 346
charlesmn 0:e0163b3111e0 347 status = sensor->vl6180_RangeStartContinuousMode(dev);
charlesmn 0:e0163b3111e0 348 printf("vl6180_RangeStartContinuousMode %d %d\n",status, dev->i2c_addr);
charlesmn 0:e0163b3111e0 349 }
charlesmn 0:e0163b3111e0 350
charlesmn 0:e0163b3111e0 351
charlesmn 0:e0163b3111e0 352 int get_sensor_data(VL6180Dev_t dev ,VL6180 *sensor)
charlesmn 0:e0163b3111e0 353 {
charlesmn 0:e0163b3111e0 354 int status;
charlesmn 0:e0163b3111e0 355 int result = 0;
charlesmn 0:e0163b3111e0 356 status = sensor->vl6180_RangeGetMeasurement(dev, &Range);
charlesmn 0:e0163b3111e0 357 if( status == 0 ){
charlesmn 0:e0163b3111e0 358 // Application must check Range.errorStatus before accessing the other data
charlesmn 0:e0163b3111e0 359 // If Range.errorStatus is DataNotReady, application knows that it has to wait a bit before getting a new data
charlesmn 0:e0163b3111e0 360 // If Range.errorStatus is 0, application knows it is a valid distance
charlesmn 0:e0163b3111e0 361 // If Range.errorStatus is not 0, application knows that reported distance is invalid so may take some decisions depending on the errorStatus
charlesmn 0:e0163b3111e0 362 if (Range.errorStatus == DataNotReady){
charlesmn 0:e0163b3111e0 363 printf("notready \n");
charlesmn 0:e0163b3111e0 364
charlesmn 0:e0163b3111e0 365 return result;
charlesmn 0:e0163b3111e0 366 }
charlesmn 0:e0163b3111e0 367
charlesmn 1:3cef7d50cab4 368 // only display the centre sensors values. All sensors values and printed out
charlesmn 0:e0163b3111e0 369 if((Range.errorStatus == 0) && (status == 0))
charlesmn 0:e0163b3111e0 370 {
charlesmn 0:e0163b3111e0 371 // only display the centre sensors values
charlesmn 0:e0163b3111e0 372 if ( dev->i2c_addr == NEW_SENSOR_CENTRE_ADDRESS )
charlesmn 0:e0163b3111e0 373 {
charlesmn 0:e0163b3111e0 374 sprintf(DISP_CurString, " %d", (int)Range.range_mm);
charlesmn 0:e0163b3111e0 375 }
charlesmn 0:e0163b3111e0 376 result = (int)Range.range_mm;
charlesmn 0:e0163b3111e0 377 }
charlesmn 0:e0163b3111e0 378 else
charlesmn 0:e0163b3111e0 379 {
charlesmn 0:e0163b3111e0 380 // only display the centre sensors values
charlesmn 0:e0163b3111e0 381 if ( dev->i2c_addr == NEW_SENSOR_CENTRE_ADDRESS )
charlesmn 0:e0163b3111e0 382 {
charlesmn 0:e0163b3111e0 383 sprintf(DISP_CurString, " %4d", 0);
charlesmn 0:e0163b3111e0 384 }
charlesmn 0:e0163b3111e0 385 result = 0;
charlesmn 0:e0163b3111e0 386 }
charlesmn 0:e0163b3111e0 387
charlesmn 0:e0163b3111e0 388
charlesmn 0:e0163b3111e0 389 /* re-arm next measurement */
charlesmn 0:e0163b3111e0 390 sensor->vl6180_ClearInterrupt(dev,INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING);
charlesmn 0:e0163b3111e0 391
charlesmn 0:e0163b3111e0 392 } // status != 0
charlesmn 0:e0163b3111e0 393 else{
charlesmn 0:e0163b3111e0 394 // it is an critical error
charlesmn 0:e0163b3111e0 395 // HandleError("critical error on VL6180x_RangeCheckAndGetMeasurement");
charlesmn 0:e0163b3111e0 396 }
charlesmn 0:e0163b3111e0 397 return result;
charlesmn 0:e0163b3111e0 398
charlesmn 0:e0163b3111e0 399 }
charlesmn 0:e0163b3111e0 400
charlesmn 0:e0163b3111e0 401
charlesmn 1:3cef7d50cab4 402 // wait_ms was removed in MBed V6.4
charlesmn 1:3cef7d50cab4 403 #if (MBED_VERSION > 60300)
charlesmn 1:3cef7d50cab4 404 void wait_ms(int ms)
charlesmn 1:3cef7d50cab4 405 {
charlesmn 1:3cef7d50cab4 406 thread_sleep_for(ms);
charlesmn 1:3cef7d50cab4 407 }
charlesmn 1:3cef7d50cab4 408 #endif
charlesmn 1:3cef7d50cab4 409
charlesmn 1:3cef7d50cab4 410
charlesmn 0:e0163b3111e0 411 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/