ST Expansion SW Team / Mbed OS VL6180_MB63_4sensors_interrupts

Dependencies:   X_NUCLEO_6180

Committer:
charlesmn
Date:
Wed Oct 28 16:21:19 2020 +0000
Revision:
0:e0163b3111e0
Child:
1:3cef7d50cab4
Sample program to control up to 4 ST VL6180 ToF sensors using interrupts to control getting data from sensors. MBed V6.3

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 0:e0163b3111e0 4 * Date : 21/10/2014 09:21:14
charlesmn 0:e0163b3111e0 5 * Description : Main program body
charlesmn 0:e0163b3111e0 6 ******************************************************************************
charlesmn 0:e0163b3111e0 7 *
charlesmn 0:e0163b3111e0 8 * COPYRIGHT(c) 2014 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 0:e0163b3111e0 59
charlesmn 0:e0163b3111e0 60 #include "mbed.h"
charlesmn 0:e0163b3111e0 61 #include "XNucleo6810.h"
charlesmn 0:e0163b3111e0 62 #include <time.h>
charlesmn 0:e0163b3111e0 63
charlesmn 0:e0163b3111e0 64 #include "spi_interface.h"
charlesmn 0:e0163b3111e0 65
charlesmn 0:e0163b3111e0 66
charlesmn 0:e0163b3111e0 67 /* Private variables ---------------------------------------------------------*/
charlesmn 0:e0163b3111e0 68
charlesmn 0:e0163b3111e0 69
charlesmn 0:e0163b3111e0 70
charlesmn 0:e0163b3111e0 71 //VL6180_SINGLE_DEVICE_DRIVER
charlesmn 0:e0163b3111e0 72
charlesmn 0:e0163b3111e0 73 // i2c tx and rx pins
charlesmn 0:e0163b3111e0 74 #define I2C_SDA D14
charlesmn 0:e0163b3111e0 75 #define I2C_SCL D15
charlesmn 0:e0163b3111e0 76
charlesmn 0:e0163b3111e0 77 /* USER CODE BEGIN 0 */
charlesmn 0:e0163b3111e0 78 #include <string.h>
charlesmn 0:e0163b3111e0 79 #include <stdlib.h>
charlesmn 0:e0163b3111e0 80 #include <stdio.h>
charlesmn 0:e0163b3111e0 81
charlesmn 0:e0163b3111e0 82 #include "vl6180_api.h"
charlesmn 0:e0163b3111e0 83 #include "6180a1.h"
charlesmn 0:e0163b3111e0 84
charlesmn 0:e0163b3111e0 85 #ifdef DEBUG
charlesmn 0:e0163b3111e0 86 //TODO
charlesmn 0:e0163b3111e0 87 #include "diag/trace.h"
charlesmn 0:e0163b3111e0 88 #define debug(msg, ...) trace_printf(msg,__VA_ARGS__)
charlesmn 0:e0163b3111e0 89 #define trace_warn(msg,...) trace_printf("W %s %d" msg "\n", __func__, __LINE__, __VA_ARGS__)
charlesmn 0:e0163b3111e0 90 #else
charlesmn 0:e0163b3111e0 91 #define debug(msg, ...) (void)0
charlesmn 0:e0163b3111e0 92 #endif
charlesmn 0:e0163b3111e0 93
charlesmn 0:e0163b3111e0 94 #define DigitDisplay_ms 1 /* ms each digit is kept on */
charlesmn 0:e0163b3111e0 95
charlesmn 0:e0163b3111e0 96
charlesmn 0:e0163b3111e0 97
charlesmn 0:e0163b3111e0 98
charlesmn 0:e0163b3111e0 99
charlesmn 0:e0163b3111e0 100 static int int_centre_result = 0;
charlesmn 0:e0163b3111e0 101 static int int_left_result = 0;
charlesmn 0:e0163b3111e0 102 static int int_right_result = 0;
charlesmn 0:e0163b3111e0 103 static int int_bottom_result = 0;
charlesmn 0:e0163b3111e0 104 static int int_result = 0;
charlesmn 0:e0163b3111e0 105
charlesmn 0:e0163b3111e0 106
charlesmn 0:e0163b3111e0 107 // timing for debug purposes
charlesmn 0:e0163b3111e0 108 uint32_t centre_polling_time_ms;
charlesmn 0:e0163b3111e0 109 uint32_t centre_start_time_ms;
charlesmn 0:e0163b3111e0 110 uint32_t centre_end_time_ms;
charlesmn 0:e0163b3111e0 111
charlesmn 0:e0163b3111e0 112 void start_sensor(VL6180Dev_t dev ,VL6180 *sensor);
charlesmn 0:e0163b3111e0 113 int get_sensor_data(VL6180Dev_t dev ,VL6180 *sensor);
charlesmn 0:e0163b3111e0 114
charlesmn 0:e0163b3111e0 115
charlesmn 0:e0163b3111e0 116 class WaitForMeasurement {
charlesmn 0:e0163b3111e0 117 public:
charlesmn 0:e0163b3111e0 118
charlesmn 0:e0163b3111e0 119
charlesmn 0:e0163b3111e0 120 // this class services the interrupts from the ToF sensors.
charlesmn 0:e0163b3111e0 121 // There is a limited amount you can do in an interrupt routine; printfs,mutexes break them among other things.
charlesmn 0:e0163b3111e0 122 // We keep things simple by only raising a flag so all the real work is done outside the interrupt.
charlesmn 0:e0163b3111e0 123 // 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 124 WaitForMeasurement(): _interrupt(A1)
charlesmn 0:e0163b3111e0 125 {
charlesmn 0:e0163b3111e0 126 }
charlesmn 0:e0163b3111e0 127
charlesmn 0:e0163b3111e0 128
charlesmn 0:e0163b3111e0 129 // constructor - Sensor is not used and can be removed
charlesmn 0:e0163b3111e0 130 WaitForMeasurement(PinName pin,MyVL6180Dev_t Dev) : _interrupt(pin) // create the InterruptIn on the pin specified to Counter
charlesmn 0:e0163b3111e0 131 {
charlesmn 0:e0163b3111e0 132 int_result = 1;
charlesmn 0:e0163b3111e0 133 Devlocal = Dev;
charlesmn 0:e0163b3111e0 134 _interrupt.rise(callback(this, &WaitForMeasurement::got_interrupt)); // attach increment function of this counter instance
charlesmn 0:e0163b3111e0 135
charlesmn 0:e0163b3111e0 136 }
charlesmn 0:e0163b3111e0 137
charlesmn 0:e0163b3111e0 138 void process_right_interrupt()
charlesmn 0:e0163b3111e0 139 {
charlesmn 0:e0163b3111e0 140 printf("processing right interrupt\n");
charlesmn 0:e0163b3111e0 141 }
charlesmn 0:e0163b3111e0 142
charlesmn 0:e0163b3111e0 143 // 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 144 void got_interrupt()
charlesmn 0:e0163b3111e0 145 {
charlesmn 0:e0163b3111e0 146
charlesmn 0:e0163b3111e0 147 _count++;
charlesmn 0:e0163b3111e0 148
charlesmn 0:e0163b3111e0 149 if (Devlocal.i2c_addr == NEW_SENSOR_CENTRE_ADDRESS)
charlesmn 0:e0163b3111e0 150 int_centre_result = 1; //flag to main that interrupt happened
charlesmn 0:e0163b3111e0 151 if (Devlocal.i2c_addr == NEW_SENSOR_LEFT_ADDRESS)
charlesmn 0:e0163b3111e0 152 int_left_result = 1; //flag to main that interrupt happened
charlesmn 0:e0163b3111e0 153 if (Devlocal.i2c_addr == NEW_SENSOR_RIGHT_ADDRESS)
charlesmn 0:e0163b3111e0 154 {
charlesmn 0:e0163b3111e0 155 int_right_result = 1; //flag to main that interrupt happened
charlesmn 0:e0163b3111e0 156 }
charlesmn 0:e0163b3111e0 157 if (Devlocal.i2c_addr == NEW_SENSOR_BOTTOM_ADDRESS)
charlesmn 0:e0163b3111e0 158 int_bottom_result = 1; //flag to main that interrupt happened
charlesmn 0:e0163b3111e0 159 }
charlesmn 0:e0163b3111e0 160
charlesmn 0:e0163b3111e0 161 //destructor
charlesmn 0:e0163b3111e0 162 ~WaitForMeasurement()
charlesmn 0:e0163b3111e0 163 {
charlesmn 0:e0163b3111e0 164 printf("destruction \n");
charlesmn 0:e0163b3111e0 165 }
charlesmn 0:e0163b3111e0 166
charlesmn 0:e0163b3111e0 167 private:
charlesmn 0:e0163b3111e0 168 InterruptIn _interrupt;
charlesmn 0:e0163b3111e0 169 volatile int _count;
charlesmn 0:e0163b3111e0 170 MyVL6180Dev_t Devlocal;
charlesmn 0:e0163b3111e0 171 int status;
charlesmn 0:e0163b3111e0 172
charlesmn 0:e0163b3111e0 173 };
charlesmn 0:e0163b3111e0 174
charlesmn 0:e0163b3111e0 175
charlesmn 0:e0163b3111e0 176
charlesmn 0:e0163b3111e0 177
charlesmn 0:e0163b3111e0 178 MyVL6180Dev_t devCentre; //data for each of the vl6180
charlesmn 0:e0163b3111e0 179 MyVL6180Dev_t devLeft;
charlesmn 0:e0163b3111e0 180 MyVL6180Dev_t devRight;
charlesmn 0:e0163b3111e0 181 MyVL6180Dev_t devBottom;
charlesmn 0:e0163b3111e0 182 VL6180Dev_t Dev = &devCentre; // the currently used vl6180
charlesmn 0:e0163b3111e0 183
charlesmn 0:e0163b3111e0 184 volatile int IntrFired=0;
charlesmn 0:e0163b3111e0 185
charlesmn 0:e0163b3111e0 186 VL6180 *Sensor;
charlesmn 0:e0163b3111e0 187
charlesmn 0:e0163b3111e0 188 static XNucleo53L1A1 *board=NULL;
charlesmn 0:e0163b3111e0 189
charlesmn 0:e0163b3111e0 190 Serial pc(SERIAL_TX, SERIAL_RX);
charlesmn 0:e0163b3111e0 191
charlesmn 0:e0163b3111e0 192 vl6180_DevI2C *dev_I2C = new vl6180_DevI2C(I2C_SDA, I2C_SCL);
charlesmn 0:e0163b3111e0 193
charlesmn 0:e0163b3111e0 194 //void WaitMilliSec(int ms);
charlesmn 0:e0163b3111e0 195
charlesmn 0:e0163b3111e0 196 /**
charlesmn 0:e0163b3111e0 197 * VL6180x CubeMX F401 i2c porting implementation
charlesmn 0:e0163b3111e0 198 */
charlesmn 0:e0163b3111e0 199
charlesmn 0:e0163b3111e0 200 #define theVL6180Dev 0x52 // what we use as "API device
charlesmn 0:e0163b3111e0 201
charlesmn 0:e0163b3111e0 202 #define i2c_bus (&hi2c1)
charlesmn 0:e0163b3111e0 203 #define def_i2c_time_out 100
charlesmn 0:e0163b3111e0 204
charlesmn 0:e0163b3111e0 205
charlesmn 0:e0163b3111e0 206 void XNUCLEO6180XA1_WaitMilliSec(int n){
charlesmn 0:e0163b3111e0 207 wait_ms(n);
charlesmn 0:e0163b3111e0 208 }
charlesmn 0:e0163b3111e0 209
charlesmn 0:e0163b3111e0 210
charlesmn 0:e0163b3111e0 211
charlesmn 0:e0163b3111e0 212
charlesmn 0:e0163b3111e0 213 /**
charlesmn 0:e0163b3111e0 214 * DISPLAY public
charlesmn 0:e0163b3111e0 215 */
charlesmn 0:e0163b3111e0 216 /*************** DISPLAY PUBLIC *********************/
charlesmn 0:e0163b3111e0 217 /*************** DISPLAY PRIVATE *********************/
charlesmn 0:e0163b3111e0 218 static char DISP_CurString[10];
charlesmn 0:e0163b3111e0 219
charlesmn 0:e0163b3111e0 220 /**
charlesmn 0:e0163b3111e0 221 * call in the main loop
charlesmn 0:e0163b3111e0 222 * when running under debugger it enable doing direct vl6180x reg access
charlesmn 0:e0163b3111e0 223 * typcilay breaking at entrance
charlesmn 0:e0163b3111e0 224 * change the the local index/data and cmd variable to do what needed
charlesmn 0:e0163b3111e0 225 * reg_cmd -1 wr byte -2wr word -3 wr dword
charlesmn 0:e0163b3111e0 226 * reg_cmd 1 rd byte 2 rd word 3 rd dword
charlesmn 0:e0163b3111e0 227 * step to last statement before return and read variable to get rd result exit
charlesmn 0:e0163b3111e0 228 */
charlesmn 0:e0163b3111e0 229
charlesmn 0:e0163b3111e0 230 void debug_stuff(void) {
charlesmn 0:e0163b3111e0 231 int reg_cmd = 0;
charlesmn 0:e0163b3111e0 232 static uint32_t reg_data;
charlesmn 0:e0163b3111e0 233 static uint16_t reg_index;
charlesmn 0:e0163b3111e0 234
charlesmn 0:e0163b3111e0 235 if (reg_cmd) {
charlesmn 0:e0163b3111e0 236 switch (reg_cmd) {
charlesmn 0:e0163b3111e0 237 case -1:
charlesmn 0:e0163b3111e0 238 VL6180_WrByte(Dev, reg_index, reg_data);
charlesmn 0:e0163b3111e0 239 debug("Wr B 0x%X = %d", reg_index, (int)reg_data);
charlesmn 0:e0163b3111e0 240 break;
charlesmn 0:e0163b3111e0 241 case -2:
charlesmn 0:e0163b3111e0 242 VL6180_WrWord(Dev, reg_index, reg_data);
charlesmn 0:e0163b3111e0 243 debug("Wr W 0x%X = %d", reg_index,(int) reg_data);
charlesmn 0:e0163b3111e0 244 break;
charlesmn 0:e0163b3111e0 245
charlesmn 0:e0163b3111e0 246 case -3:
charlesmn 0:e0163b3111e0 247 VL6180_WrDWord(Dev, reg_index, reg_data);
charlesmn 0:e0163b3111e0 248 debug("WrDW 0x%X = %d", reg_index, (int)reg_data);
charlesmn 0:e0163b3111e0 249 break;
charlesmn 0:e0163b3111e0 250
charlesmn 0:e0163b3111e0 251 case 1:
charlesmn 0:e0163b3111e0 252 reg_data=0;
charlesmn 0:e0163b3111e0 253 VL6180_RdByte(Dev, reg_index, (uint8_t*)&reg_data);
charlesmn 0:e0163b3111e0 254 debug("RD B 0x%X = %d", reg_index, (int)reg_data);
charlesmn 0:e0163b3111e0 255 break;
charlesmn 0:e0163b3111e0 256 case 2:
charlesmn 0:e0163b3111e0 257 reg_data=0;
charlesmn 0:e0163b3111e0 258 VL6180_RdWord(Dev, reg_index, (uint16_t*)&reg_data);
charlesmn 0:e0163b3111e0 259 debug("RD W 0x%X = %d", reg_index, (int)reg_data);
charlesmn 0:e0163b3111e0 260 break;
charlesmn 0:e0163b3111e0 261
charlesmn 0:e0163b3111e0 262 case 3:
charlesmn 0:e0163b3111e0 263 VL6180_RdDWord(Dev, reg_index, &reg_data);
charlesmn 0:e0163b3111e0 264 debug("RD DW 0x%X = %d", reg_index, (int)reg_data);
charlesmn 0:e0163b3111e0 265 break;
charlesmn 0:e0163b3111e0 266 default:
charlesmn 0:e0163b3111e0 267 debug("Invalid command %d", reg_cmd);
charlesmn 0:e0163b3111e0 268 /* nothing to do*/
charlesmn 0:e0163b3111e0 269 ;
charlesmn 0:e0163b3111e0 270 }
charlesmn 0:e0163b3111e0 271 }
charlesmn 0:e0163b3111e0 272 }
charlesmn 0:e0163b3111e0 273
charlesmn 0:e0163b3111e0 274
charlesmn 0:e0163b3111e0 275 volatile int VL6180_IsrFired=0;
charlesmn 0:e0163b3111e0 276
charlesmn 0:e0163b3111e0 277
charlesmn 0:e0163b3111e0 278 char buffer[10];
charlesmn 0:e0163b3111e0 279
charlesmn 0:e0163b3111e0 280
charlesmn 0:e0163b3111e0 281 uint32_t TimeStarted; /* various display and mode delay starting time */
charlesmn 0:e0163b3111e0 282 VL6180_RangeData_t Range; /* Range measurmeent */
charlesmn 0:e0163b3111e0 283 uint16_t range; /* range average distance */
charlesmn 0:e0163b3111e0 284
charlesmn 0:e0163b3111e0 285
charlesmn 0:e0163b3111e0 286 /* USER CODE END 0 */
charlesmn 0:e0163b3111e0 287
charlesmn 0:e0163b3111e0 288 /* Private function prototypes -----------------------------------------------*/
charlesmn 0:e0163b3111e0 289
charlesmn 0:e0163b3111e0 290 int main(void)
charlesmn 0:e0163b3111e0 291 {
charlesmn 0:e0163b3111e0 292
charlesmn 0:e0163b3111e0 293 WaitForMeasurement* int1; // the interrupt handler
charlesmn 0:e0163b3111e0 294 WaitForMeasurement* int2; // the interrupt handler
charlesmn 0:e0163b3111e0 295 WaitForMeasurement* int3; // the interrupt handler
charlesmn 0:e0163b3111e0 296 WaitForMeasurement* int4; // the interrupt handler
charlesmn 0:e0163b3111e0 297
charlesmn 0:e0163b3111e0 298 pc.baud(115200); // baud rate is important as printf statements take a lot of time
charlesmn 0:e0163b3111e0 299
charlesmn 0:e0163b3111e0 300
charlesmn 0:e0163b3111e0 301 //create I2C channel
charlesmn 0:e0163b3111e0 302 vl6180_DevI2C *dev_I2C = new vl6180_DevI2C(I2C_SDA, I2C_SCL);
charlesmn 0:e0163b3111e0 303
charlesmn 0:e0163b3111e0 304 dev_I2C->frequency(400000); //also needs doing in spi_interface.c
charlesmn 0:e0163b3111e0 305 devCentre.i2c_addr = theVL6180Dev; // set to default adress for now
charlesmn 0:e0163b3111e0 306
charlesmn 0:e0163b3111e0 307 int status;
charlesmn 0:e0163b3111e0 308
charlesmn 0:e0163b3111e0 309 // create instances for the sensors
charlesmn 0:e0163b3111e0 310 board = XNucleo53L1A1::instance(dev_I2C, A3, D13, D2 ,A2);
charlesmn 0:e0163b3111e0 311 // find the sensors we have and initialise
charlesmn 0:e0163b3111e0 312 status = board->init_board();
charlesmn 0:e0163b3111e0 313 if (status) {
charlesmn 0:e0163b3111e0 314 printf("Failed to init board!\r\n");
charlesmn 0:e0163b3111e0 315 return 0;
charlesmn 0:e0163b3111e0 316 }
charlesmn 0:e0163b3111e0 317
charlesmn 0:e0163b3111e0 318
charlesmn 0:e0163b3111e0 319 //select centre sensor
charlesmn 0:e0163b3111e0 320 if (board->sensor_centre != NULL ) {
charlesmn 0:e0163b3111e0 321 devCentre.i2c_addr = NEW_SENSOR_CENTRE_ADDRESS;
charlesmn 0:e0163b3111e0 322 Dev = &devCentre;
charlesmn 0:e0163b3111e0 323 Sensor=board->sensor_centre;
charlesmn 0:e0163b3111e0 324 int1 = new WaitForMeasurement(A3,devCentre); // create a interrupt class for this interrupt pin
charlesmn 0:e0163b3111e0 325 start_sensor(Dev ,Sensor);
charlesmn 0:e0163b3111e0 326 }
charlesmn 0:e0163b3111e0 327
charlesmn 0:e0163b3111e0 328 if (board->sensor_left != NULL ) {
charlesmn 0:e0163b3111e0 329 devLeft.i2c_addr = NEW_SENSOR_LEFT_ADDRESS;
charlesmn 0:e0163b3111e0 330 Dev = &devLeft;
charlesmn 0:e0163b3111e0 331 Sensor=board->sensor_left;
charlesmn 0:e0163b3111e0 332 int2 = new WaitForMeasurement(D13,devLeft); // create a interrupt class for this interrupt pin
charlesmn 0:e0163b3111e0 333 start_sensor(Dev ,Sensor);
charlesmn 0:e0163b3111e0 334 }
charlesmn 0:e0163b3111e0 335
charlesmn 0:e0163b3111e0 336 if (board->sensor_right != NULL ) {
charlesmn 0:e0163b3111e0 337 devRight.i2c_addr = NEW_SENSOR_RIGHT_ADDRESS;
charlesmn 0:e0163b3111e0 338 Dev = &devRight;
charlesmn 0:e0163b3111e0 339 Sensor=board->sensor_right;
charlesmn 0:e0163b3111e0 340 int2 = new WaitForMeasurement(D2,devRight); // create a interrupt class for this interrupt pin
charlesmn 0:e0163b3111e0 341 start_sensor(Dev ,Sensor);
charlesmn 0:e0163b3111e0 342 }
charlesmn 0:e0163b3111e0 343
charlesmn 0:e0163b3111e0 344 if (board->sensor_bottom != NULL ) {
charlesmn 0:e0163b3111e0 345 devBottom.i2c_addr = NEW_SENSOR_BOTTOM_ADDRESS;
charlesmn 0:e0163b3111e0 346 Dev = &devBottom;
charlesmn 0:e0163b3111e0 347 Sensor=board->sensor_bottom;
charlesmn 0:e0163b3111e0 348 int2 = new WaitForMeasurement(A2,devBottom); // create a interrupt class for this interrupt pin
charlesmn 0:e0163b3111e0 349 start_sensor(Dev ,Sensor);
charlesmn 0:e0163b3111e0 350 }
charlesmn 0:e0163b3111e0 351
charlesmn 0:e0163b3111e0 352
charlesmn 0:e0163b3111e0 353
charlesmn 0:e0163b3111e0 354 /* Infinite loop */
charlesmn 0:e0163b3111e0 355 while (1) {
charlesmn 0:e0163b3111e0 356
charlesmn 0:e0163b3111e0 357 if ( int_centre_result == 1 )
charlesmn 0:e0163b3111e0 358 {
charlesmn 0:e0163b3111e0 359 int_centre_result = 0; //clear interrupt flag
charlesmn 0:e0163b3111e0 360 Dev = &devCentre;
charlesmn 0:e0163b3111e0 361 Sensor=board->sensor_centre;
charlesmn 0:e0163b3111e0 362
charlesmn 0:e0163b3111e0 363 int result = get_sensor_data(Dev , Sensor);
charlesmn 0:e0163b3111e0 364 if ( result != 0)
charlesmn 0:e0163b3111e0 365 printf("C %d \n",result);
charlesmn 0:e0163b3111e0 366 }
charlesmn 0:e0163b3111e0 367
charlesmn 0:e0163b3111e0 368 if ( int_left_result == 1 )
charlesmn 0:e0163b3111e0 369 {
charlesmn 0:e0163b3111e0 370 int_left_result = 0; //clear interrupt flag
charlesmn 0:e0163b3111e0 371 Dev = &devLeft;
charlesmn 0:e0163b3111e0 372 Sensor=board->sensor_left;
charlesmn 0:e0163b3111e0 373
charlesmn 0:e0163b3111e0 374 int result = get_sensor_data(Dev , Sensor);
charlesmn 0:e0163b3111e0 375 if ( result != 0)
charlesmn 0:e0163b3111e0 376 printf("L %d \n",result);
charlesmn 0:e0163b3111e0 377 }
charlesmn 0:e0163b3111e0 378
charlesmn 0:e0163b3111e0 379 if ( int_right_result == 1 )
charlesmn 0:e0163b3111e0 380 {
charlesmn 0:e0163b3111e0 381 int_right_result = 0; //clear interrupt flag
charlesmn 0:e0163b3111e0 382 Dev = &devRight;
charlesmn 0:e0163b3111e0 383 Sensor=board->sensor_right;
charlesmn 0:e0163b3111e0 384
charlesmn 0:e0163b3111e0 385 int result = get_sensor_data(Dev , Sensor);
charlesmn 0:e0163b3111e0 386 if ( result != 0)
charlesmn 0:e0163b3111e0 387 printf("R %d \n",result);
charlesmn 0:e0163b3111e0 388 }
charlesmn 0:e0163b3111e0 389
charlesmn 0:e0163b3111e0 390 if ( int_bottom_result == 1 )
charlesmn 0:e0163b3111e0 391 {
charlesmn 0:e0163b3111e0 392 int_bottom_result = 0; //clear interrupt flag
charlesmn 0:e0163b3111e0 393 Dev = &devBottom;
charlesmn 0:e0163b3111e0 394 Sensor=board->sensor_bottom;
charlesmn 0:e0163b3111e0 395
charlesmn 0:e0163b3111e0 396 int result = get_sensor_data(Dev , Sensor);
charlesmn 0:e0163b3111e0 397 if ( result != 0)
charlesmn 0:e0163b3111e0 398 printf("B %d \n",result);
charlesmn 0:e0163b3111e0 399 }
charlesmn 0:e0163b3111e0 400
charlesmn 0:e0163b3111e0 401
charlesmn 0:e0163b3111e0 402 // the display is very simple and requires written to frequently so
charlesmn 0:e0163b3111e0 403 // we are writing to the display when we would normally sleep.
charlesmn 0:e0163b3111e0 404 // when we are not writing to the display it is blank
charlesmn 0:e0163b3111e0 405 {
charlesmn 0:e0163b3111e0 406 for (int i = 0 ;i < 10;i++)
charlesmn 0:e0163b3111e0 407 { // write to display
charlesmn 0:e0163b3111e0 408 XNUCLEO6180XA1_DisplayString(DISP_CurString, DigitDisplay_ms* 5);
charlesmn 0:e0163b3111e0 409 }
charlesmn 0:e0163b3111e0 410 }
charlesmn 0:e0163b3111e0 411
charlesmn 0:e0163b3111e0 412 // debug_stuff();
charlesmn 0:e0163b3111e0 413 }
charlesmn 0:e0163b3111e0 414
charlesmn 0:e0163b3111e0 415 }
charlesmn 0:e0163b3111e0 416
charlesmn 0:e0163b3111e0 417
charlesmn 0:e0163b3111e0 418 void start_sensor(VL6180Dev_t dev ,VL6180 *sensor)
charlesmn 0:e0163b3111e0 419 {
charlesmn 0:e0163b3111e0 420
charlesmn 0:e0163b3111e0 421 /* Note that if we waited 1msec we could bypass VL6180_WaitDeviceBooted(&Dev); */
charlesmn 0:e0163b3111e0 422 int status;
charlesmn 0:e0163b3111e0 423 status = sensor->vl6180_WaitDeviceBooted(dev);
charlesmn 0:e0163b3111e0 424 printf("vl6180_WaitDeviceBooted %d %d\n",status, dev->i2c_addr);
charlesmn 0:e0163b3111e0 425 status = sensor->vl6180_InitData(dev);
charlesmn 0:e0163b3111e0 426 printf("vl6180_InitData %d %d\n",status, dev->i2c_addr);
charlesmn 0:e0163b3111e0 427
charlesmn 0:e0163b3111e0 428 status = sensor->vl6180_FilterSetState(dev,0); // disbale as not effective in continuous mose
charlesmn 0:e0163b3111e0 429 printf("vl6180_FilterSetState %d \n",status);
charlesmn 0:e0163b3111e0 430 status = sensor->vl6180_Prepare(dev); // sensor init
charlesmn 0:e0163b3111e0 431 printf("vl6180_Prepare %d \n",status);
charlesmn 0:e0163b3111e0 432
charlesmn 0:e0163b3111e0 433 status = sensor->vl6180_UpscaleSetScaling(dev, 2); // set scaling by 2 to get ranging in range 0 to 400mm
charlesmn 0:e0163b3111e0 434 printf("vl6180_UpscaleSetScaling %d \n",status);
charlesmn 0:e0163b3111e0 435
charlesmn 0:e0163b3111e0 436 // if slow reaction is enough then set a high time like 100 ms (up to 2550 msec)
charlesmn 0:e0163b3111e0 437 // if fastest reaction is required then set 0 that will set minimal possible
charlesmn 0:e0163b3111e0 438 status = sensor->vl6180_RangeSetInterMeasPeriod(dev, 100);
charlesmn 0:e0163b3111e0 439 printf("vl6180_RangeSetInterMeasPeriod %d \n",status);
charlesmn 0:e0163b3111e0 440 // set vl6180x gpio1 pin to range interrupt output with high polarity (rising edge)
charlesmn 0:e0163b3111e0 441 status = sensor->vl6180_SetupGPIO1(dev, GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT, INTR_POL_HIGH);
charlesmn 0:e0163b3111e0 442 printf("vl6180_SetupGPIO1 %d \n",status);
charlesmn 0:e0163b3111e0 443 // set range interrupt reporting to low threshold
charlesmn 0:e0163b3111e0 444 status = sensor->vl6180_RangeConfigInterrupt(dev, CONFIG_GPIO_INTERRUPT_LEVEL_LOW);
charlesmn 0:e0163b3111e0 445 printf("vl6180_RangeConfigInterrupt %d \n",status);
charlesmn 0:e0163b3111e0 446 // we don't care of high threshold as we don't use it , group hold is managed externaly
charlesmn 0:e0163b3111e0 447 status = sensor->vl6180_RangeSetThresholds(dev, 100, 00, 0);
charlesmn 0:e0163b3111e0 448 printf("vl6180_RangeSetThresholds %d %d\n",status, dev->i2c_addr);
charlesmn 0:e0163b3111e0 449
charlesmn 0:e0163b3111e0 450 status = sensor->vl6180_ClearInterrupt(dev,INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING);
charlesmn 0:e0163b3111e0 451 printf("vl6180_ClearInterrupt %d \n",status);
charlesmn 0:e0163b3111e0 452
charlesmn 0:e0163b3111e0 453 status = sensor->vl6180_RangeStartContinuousMode(dev);
charlesmn 0:e0163b3111e0 454 printf("vl6180_RangeStartContinuousMode %d %d\n",status, dev->i2c_addr);
charlesmn 0:e0163b3111e0 455 }
charlesmn 0:e0163b3111e0 456
charlesmn 0:e0163b3111e0 457
charlesmn 0:e0163b3111e0 458 int get_sensor_data(VL6180Dev_t dev ,VL6180 *sensor)
charlesmn 0:e0163b3111e0 459 {
charlesmn 0:e0163b3111e0 460 int status;
charlesmn 0:e0163b3111e0 461 int result = 0;
charlesmn 0:e0163b3111e0 462 status = sensor->vl6180_RangeGetMeasurement(dev, &Range);
charlesmn 0:e0163b3111e0 463 if( status == 0 ){
charlesmn 0:e0163b3111e0 464 // Application must check Range.errorStatus before accessing the other data
charlesmn 0:e0163b3111e0 465 // If Range.errorStatus is DataNotReady, application knows that it has to wait a bit before getting a new data
charlesmn 0:e0163b3111e0 466 // If Range.errorStatus is 0, application knows it is a valid distance
charlesmn 0:e0163b3111e0 467 // 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 468 if (Range.errorStatus == DataNotReady){
charlesmn 0:e0163b3111e0 469 printf("notready \n");
charlesmn 0:e0163b3111e0 470
charlesmn 0:e0163b3111e0 471 return result;
charlesmn 0:e0163b3111e0 472 }
charlesmn 0:e0163b3111e0 473
charlesmn 0:e0163b3111e0 474 // only display the centre sensors values
charlesmn 0:e0163b3111e0 475
charlesmn 0:e0163b3111e0 476 if((Range.errorStatus == 0) && (status == 0))
charlesmn 0:e0163b3111e0 477 {
charlesmn 0:e0163b3111e0 478 // only display the centre sensors values
charlesmn 0:e0163b3111e0 479 if ( dev->i2c_addr == NEW_SENSOR_CENTRE_ADDRESS )
charlesmn 0:e0163b3111e0 480 {
charlesmn 0:e0163b3111e0 481 sprintf(DISP_CurString, " %d", (int)Range.range_mm);
charlesmn 0:e0163b3111e0 482 }
charlesmn 0:e0163b3111e0 483 result = (int)Range.range_mm;
charlesmn 0:e0163b3111e0 484 }
charlesmn 0:e0163b3111e0 485 else
charlesmn 0:e0163b3111e0 486 {
charlesmn 0:e0163b3111e0 487 // only display the centre sensors values
charlesmn 0:e0163b3111e0 488 if ( dev->i2c_addr == NEW_SENSOR_CENTRE_ADDRESS )
charlesmn 0:e0163b3111e0 489 {
charlesmn 0:e0163b3111e0 490 sprintf(DISP_CurString, " %4d", 0);
charlesmn 0:e0163b3111e0 491 }
charlesmn 0:e0163b3111e0 492 result = 0;
charlesmn 0:e0163b3111e0 493 }
charlesmn 0:e0163b3111e0 494
charlesmn 0:e0163b3111e0 495
charlesmn 0:e0163b3111e0 496 /* re-arm next measurement */
charlesmn 0:e0163b3111e0 497 sensor->vl6180_ClearInterrupt(dev,INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING);
charlesmn 0:e0163b3111e0 498
charlesmn 0:e0163b3111e0 499 } // status != 0
charlesmn 0:e0163b3111e0 500 else{
charlesmn 0:e0163b3111e0 501 // it is an critical error
charlesmn 0:e0163b3111e0 502 // HandleError("critical error on VL6180x_RangeCheckAndGetMeasurement");
charlesmn 0:e0163b3111e0 503 }
charlesmn 0:e0163b3111e0 504 return result;
charlesmn 0:e0163b3111e0 505
charlesmn 0:e0163b3111e0 506 }
charlesmn 0:e0163b3111e0 507
charlesmn 0:e0163b3111e0 508
charlesmn 0:e0163b3111e0 509 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/