ST Expansion SW Team / Mbed OS VL6180_MB63_1sensor_singleshot_poll

Dependencies:   X_NUCLEO_6180

Committer:
charlesmn
Date:
Thu Oct 29 09:23:00 2020 +0000
Revision:
0:d96995e87b29
Child:
1:43a9bc2f05b5
This program controls a VL6180 ToF sensor running on an STM32F401 card with the VL6180 shield. It works in single shot mode where the program polls for the measurement. Result is outputted to the Screen. MBed V6.3

Who changed what in which revision?

UserRevisionLine numberNew contents of line
charlesmn 0:d96995e87b29 1 /**
charlesmn 0:d96995e87b29 2 ******************************************************************************
charlesmn 0:d96995e87b29 3 * File Name : main.c
charlesmn 0:d96995e87b29 4 * Date : 29/10/2020
charlesmn 0:d96995e87b29 5 * Description : Main program body
charlesmn 0:d96995e87b29 6 ******************************************************************************
charlesmn 0:d96995e87b29 7 *
charlesmn 0:d96995e87b29 8 * COPYRIGHT(c) 2020 STMicroelectronics
charlesmn 0:d96995e87b29 9 *
charlesmn 0:d96995e87b29 10 * Redistribution and use in source and binary forms, with or without modification,
charlesmn 0:d96995e87b29 11 * are permitted provided that the following conditions are met:
charlesmn 0:d96995e87b29 12 * 1. Redistributions of source code must retain the above copyright notice,
charlesmn 0:d96995e87b29 13 * this list of conditions and the following disclaimer.
charlesmn 0:d96995e87b29 14 * 2. Redistributions in binary form must reproduce the above copyright notice,
charlesmn 0:d96995e87b29 15 * this list of conditions and the following disclaimer in the documentation
charlesmn 0:d96995e87b29 16 * and/or other materials provided with the distribution.
charlesmn 0:d96995e87b29 17 * 3. Neither the name of STMicroelectronics nor the names of its contributors
charlesmn 0:d96995e87b29 18 * may be used to endorse or promote products derived from this software
charlesmn 0:d96995e87b29 19 * without specific prior written permission.
charlesmn 0:d96995e87b29 20 *
charlesmn 0:d96995e87b29 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
charlesmn 0:d96995e87b29 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
charlesmn 0:d96995e87b29 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
charlesmn 0:d96995e87b29 24 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
charlesmn 0:d96995e87b29 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
charlesmn 0:d96995e87b29 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
charlesmn 0:d96995e87b29 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
charlesmn 0:d96995e87b29 28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
charlesmn 0:d96995e87b29 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
charlesmn 0:d96995e87b29 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
charlesmn 0:d96995e87b29 31 *
charlesmn 0:d96995e87b29 32 ******************************************************************************
charlesmn 0:d96995e87b29 33 This program controls a VL6180 ToF sensor running on an STM32F401 card with the
charlesmn 0:d96995e87b29 34 VL6180 shield. This program works in single shot mode where the program polls for
charlesmn 0:d96995e87b29 35 the measurement finishing. This allows for the display to be updated while the
charlesmn 0:d96995e87b29 36 measurement occurs.
charlesmn 0:d96995e87b29 37
charlesmn 0:d96995e87b29 38 The display is very crude with no storing of the last digits, each digit is written
charlesmn 0:d96995e87b29 39 and then a wait occurs and then the next digit is written. This means that a lot of time is
charlesmn 0:d96995e87b29 40 taken writing the display and any long period when the display is not serviced
charlesmn 0:d96995e87b29 41 will cause the display to flicker.
charlesmn 0:d96995e87b29 42
charlesmn 0:d96995e87b29 43 In this program access to the VL6180 api is through wrapper functions in
charlesmn 0:d96995e87b29 44 vl6180_class.cpp. It is also possible to access the api directly. E.G both the lines below
charlesmn 0:d96995e87b29 45 do the same thing.
charlesmn 0:d96995e87b29 46
charlesmn 0:d96995e87b29 47 status = VL6180_ClearInterrupt(dev,INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING);
charlesmn 0:d96995e87b29 48 status = sensor->vl6180_ClearInterrupt(dev,INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING);
charlesmn 0:d96995e87b29 49 */
charlesmn 0:d96995e87b29 50
charlesmn 0:d96995e87b29 51
charlesmn 0:d96995e87b29 52 /* Includes ------------------------------------------------------------------*/
charlesmn 0:d96995e87b29 53 //#include "stm32xxx_hal.h"
charlesmn 0:d96995e87b29 54
charlesmn 0:d96995e87b29 55 /* Private variables ---------------------------------------------------------*/
charlesmn 0:d96995e87b29 56
charlesmn 0:d96995e87b29 57 #include <stdio.h>
charlesmn 0:d96995e87b29 58
charlesmn 0:d96995e87b29 59 #include "mbed.h"
charlesmn 0:d96995e87b29 60 #include "XNucleo6810.h"
charlesmn 0:d96995e87b29 61 #include <time.h>
charlesmn 0:d96995e87b29 62
charlesmn 0:d96995e87b29 63 #include "spi_interface.h"
charlesmn 0:d96995e87b29 64
charlesmn 0:d96995e87b29 65
charlesmn 0:d96995e87b29 66 //VL6180_SINGLE_DEVICE_DRIVER
charlesmn 0:d96995e87b29 67
charlesmn 0:d96995e87b29 68
charlesmn 0:d96995e87b29 69 #define VL6180_I2C_SDA D14
charlesmn 0:d96995e87b29 70 #define VL6180_I2C_SCL D15
charlesmn 0:d96995e87b29 71
charlesmn 0:d96995e87b29 72 /* USER CODE BEGIN 0 */
charlesmn 0:d96995e87b29 73 #include <string.h>
charlesmn 0:d96995e87b29 74 #include <stdlib.h>
charlesmn 0:d96995e87b29 75 #include <stdio.h>
charlesmn 0:d96995e87b29 76
charlesmn 0:d96995e87b29 77 #include "vl6180_api.h"
charlesmn 0:d96995e87b29 78 #include "6180a1.h"
charlesmn 0:d96995e87b29 79
charlesmn 0:d96995e87b29 80 #ifdef DEBUG
charlesmn 0:d96995e87b29 81 //TODO
charlesmn 0:d96995e87b29 82 #include "diag/trace.h"
charlesmn 0:d96995e87b29 83 #define debug(msg, ...) trace_printf(msg,__VA_ARGS__)
charlesmn 0:d96995e87b29 84 #define trace_warn(msg,...) trace_printf("W %s %d" msg "\n", __func__, __LINE__, __VA_ARGS__)
charlesmn 0:d96995e87b29 85 #else
charlesmn 0:d96995e87b29 86 #define debug(msg, ...) (void)0
charlesmn 0:d96995e87b29 87 #endif
charlesmn 0:d96995e87b29 88
charlesmn 0:d96995e87b29 89 #define DigitDisplay_ms 1 /* ms each digit is kept on */
charlesmn 0:d96995e87b29 90 #if VL6180_HAVE_DMAX_RANGING
charlesmn 0:d96995e87b29 91 #define DMaxDispTime 0 /* Set to 1000 to display Dmax during 1 sec when no target is detected */
charlesmn 0:d96995e87b29 92 #else
charlesmn 0:d96995e87b29 93 #define DMaxDispTime 0
charlesmn 0:d96995e87b29 94 #endif
charlesmn 0:d96995e87b29 95
charlesmn 0:d96995e87b29 96
charlesmn 0:d96995e87b29 97 MyVL6180Dev_t devCentre; //data for each of the vl6180
charlesmn 0:d96995e87b29 98 MyVL6180Dev_t devLeft;
charlesmn 0:d96995e87b29 99 MyVL6180Dev_t devRight;
charlesmn 0:d96995e87b29 100 MyVL6180Dev_t devBottom;
charlesmn 0:d96995e87b29 101 VL6180Dev_t Dev = &devCentre; // the currently used vl6180
charlesmn 0:d96995e87b29 102
charlesmn 0:d96995e87b29 103 volatile int IntrFired=0;
charlesmn 0:d96995e87b29 104
charlesmn 0:d96995e87b29 105 VL6180 *Sensor;
charlesmn 0:d96995e87b29 106
charlesmn 0:d96995e87b29 107 static XNucleo53L1A1 *board=NULL;
charlesmn 0:d96995e87b29 108
charlesmn 0:d96995e87b29 109 Serial pc(SERIAL_TX, SERIAL_RX);
charlesmn 0:d96995e87b29 110
charlesmn 0:d96995e87b29 111 vl6180_DevI2C *dev_I2C = new vl6180_DevI2C(VL6180_I2C_SDA, VL6180_I2C_SCL);
charlesmn 0:d96995e87b29 112
charlesmn 0:d96995e87b29 113 #define theVL6180Dev 0x52 // what we use as "API device
charlesmn 0:d96995e87b29 114
charlesmn 0:d96995e87b29 115 #define i2c_bus (&hi2c1)
charlesmn 0:d96995e87b29 116 #define def_i2c_time_out 100
charlesmn 0:d96995e87b29 117
charlesmn 0:d96995e87b29 118
charlesmn 0:d96995e87b29 119 void XNUCLEO6180XA1_WaitMilliSec(int n){
charlesmn 0:d96995e87b29 120 wait_ms(n);
charlesmn 0:d96995e87b29 121 }
charlesmn 0:d96995e87b29 122
charlesmn 0:d96995e87b29 123
charlesmn 0:d96995e87b29 124
charlesmn 0:d96995e87b29 125
charlesmn 0:d96995e87b29 126 /**
charlesmn 0:d96995e87b29 127 * DISPLAY public
charlesmn 0:d96995e87b29 128 */
charlesmn 0:d96995e87b29 129 /*************** DISPLAY PUBLIC *********************/
charlesmn 0:d96995e87b29 130 /*************** DISPLAY PRIVATE *********************/
charlesmn 0:d96995e87b29 131 static char DISP_CurString[10]; // the strin g to be displayed on the screen
charlesmn 0:d96995e87b29 132
charlesmn 0:d96995e87b29 133 char buffer[10];
charlesmn 0:d96995e87b29 134
charlesmn 0:d96995e87b29 135
charlesmn 0:d96995e87b29 136 uint32_t TimeStarted; /* various display and mode delay starting time */
charlesmn 0:d96995e87b29 137 VL6180_RangeData_t Range; /* Range measurmeent */
charlesmn 0:d96995e87b29 138 uint16_t range; /* range average distance */
charlesmn 0:d96995e87b29 139
charlesmn 0:d96995e87b29 140
charlesmn 0:d96995e87b29 141 /* USER CODE END 0 */
charlesmn 0:d96995e87b29 142
charlesmn 0:d96995e87b29 143 /* Private function prototypes -----------------------------------------------*/
charlesmn 0:d96995e87b29 144
charlesmn 0:d96995e87b29 145 int main(void)
charlesmn 0:d96995e87b29 146 {
charlesmn 0:d96995e87b29 147 pc.baud(115200); // baud rate is important as printf statements take a lot of time
charlesmn 0:d96995e87b29 148 devCentre.i2c_addr = theVL6180Dev; // set to default adress for now
charlesmn 0:d96995e87b29 149 printf("vl6180_ss_and_poll_ranging \n");
charlesmn 0:d96995e87b29 150
charlesmn 0:d96995e87b29 151 int status;
charlesmn 0:d96995e87b29 152
charlesmn 0:d96995e87b29 153 // create instances for the sensors
charlesmn 0:d96995e87b29 154 board = XNucleo53L1A1::instance(dev_I2C, A2, D8, D2 ,D2);
charlesmn 0:d96995e87b29 155
charlesmn 0:d96995e87b29 156 // find the sensors we have and initialise
charlesmn 0:d96995e87b29 157 status = board->init_board();
charlesmn 0:d96995e87b29 158 if (status) {
charlesmn 0:d96995e87b29 159 printf("Failed to init board!\r\n");
charlesmn 0:d96995e87b29 160 return 0;
charlesmn 0:d96995e87b29 161 }
charlesmn 0:d96995e87b29 162
charlesmn 0:d96995e87b29 163 //select centre sensor
charlesmn 0:d96995e87b29 164 devCentre.i2c_addr = NEW_SENSOR_CENTRE_ADDRESS;
charlesmn 0:d96995e87b29 165 Dev = &devCentre;
charlesmn 0:d96995e87b29 166 Sensor=board->sensor_centre;
charlesmn 0:d96995e87b29 167 if ( board->sensor_centre ==NULL)
charlesmn 0:d96995e87b29 168 printf("board->sensor_centre = Null\n");
charlesmn 0:d96995e87b29 169
charlesmn 0:d96995e87b29 170 /* Note that as we waited 1msec we could bypass VL6180_WaitDeviceBooted(&Dev); */
charlesmn 0:d96995e87b29 171 Sensor->vl6180_WaitDeviceBooted(Dev);
charlesmn 0:d96995e87b29 172 Sensor->vl6180_InitData(Dev);
charlesmn 0:d96995e87b29 173
charlesmn 0:d96995e87b29 174 printf("started interrupt centre %d\n",status);
charlesmn 0:d96995e87b29 175
charlesmn 0:d96995e87b29 176 /* Enable Dmax calculation only if value is displayed (to save computation power) */
charlesmn 0:d96995e87b29 177 Sensor->vl6180_DMaxSetState(Dev, DMaxDispTime>0);
charlesmn 0:d96995e87b29 178 status = Sensor->vl6180_Prepare(Dev);
charlesmn 0:d96995e87b29 179
charlesmn 0:d96995e87b29 180 VL6180_ClearInterrupt(Dev, INTERRUPT_CLEAR_RANGING);
charlesmn 0:d96995e87b29 181
charlesmn 0:d96995e87b29 182 /* kick off the first measurement */
charlesmn 0:d96995e87b29 183 status = Sensor->vl6180_RangeStartSingleShot(Dev);
charlesmn 0:d96995e87b29 184
charlesmn 0:d96995e87b29 185 printf("start loop \n");
charlesmn 0:d96995e87b29 186 /* Infinite loop */
charlesmn 0:d96995e87b29 187 while (1) {
charlesmn 0:d96995e87b29 188 status = Sensor->vl6180_RangeGetMeasurementIfReady(Dev, &Range);
charlesmn 0:d96995e87b29 189 if( status == 0 ){
charlesmn 0:d96995e87b29 190 // Application must check Range.errorStatus before accessing the other data
charlesmn 0:d96995e87b29 191 // If Range.errorStatus is DataNotReady, application knows that it has to wait a bit before getting a new data
charlesmn 0:d96995e87b29 192 // If Range.errorStatus is 0, application knows it is a valid distance
charlesmn 0:d96995e87b29 193 // If Range.errorStatus is not 0, application knows that reported distance is invalid so may take some decisions depending on the errorStatus
charlesmn 0:d96995e87b29 194 if (Range.errorStatus == DataNotReady)
charlesmn 0:d96995e87b29 195 continue;
charlesmn 0:d96995e87b29 196
charlesmn 0:d96995e87b29 197 if((Range.errorStatus == 0) && (status == 0))
charlesmn 0:d96995e87b29 198 {
charlesmn 0:d96995e87b29 199 // printf("range = %d\n",Range.range_mm); //output result to serial port
charlesmn 0:d96995e87b29 200 sprintf(DISP_CurString, " %d", (int)Range.range_mm);
charlesmn 0:d96995e87b29 201 }
charlesmn 0:d96995e87b29 202 else
charlesmn 0:d96995e87b29 203 {
charlesmn 0:d96995e87b29 204 sprintf(DISP_CurString, " %d", 0);
charlesmn 0:d96995e87b29 205 }
charlesmn 0:d96995e87b29 206
charlesmn 0:d96995e87b29 207 /* re-arm next measurement */
charlesmn 0:d96995e87b29 208 status = Sensor->vl6180_RangeStartSingleShot(Dev);
charlesmn 0:d96995e87b29 209 }
charlesmn 0:d96995e87b29 210 else{
charlesmn 0:d96995e87b29 211 // it is an critical error
charlesmn 0:d96995e87b29 212 // HandleError("critical error on VL6180x_RangeCheckAndGetMeasurement");
charlesmn 0:d96995e87b29 213 }
charlesmn 0:d96995e87b29 214
charlesmn 0:d96995e87b29 215
charlesmn 0:d96995e87b29 216 // the display is very simple and requires written to frequently so
charlesmn 0:d96995e87b29 217 // we are writing to the display when we would normally sleep.
charlesmn 0:d96995e87b29 218 // when we are not writing to the display it is blank
charlesmn 0:d96995e87b29 219 for (int i = 0 ;i < 20;i++)
charlesmn 0:d96995e87b29 220 {
charlesmn 0:d96995e87b29 221 XNUCLEO6180XA1_DisplayString(DISP_CurString, DigitDisplay_ms* 5);
charlesmn 0:d96995e87b29 222 }
charlesmn 0:d96995e87b29 223
charlesmn 0:d96995e87b29 224 }
charlesmn 0:d96995e87b29 225
charlesmn 0:d96995e87b29 226 }
charlesmn 0:d96995e87b29 227
charlesmn 0:d96995e87b29 228
charlesmn 0:d96995e87b29 229 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/