Thundersoft
/
VL6180XA1_for_TT_Mxx
Creating a project about VL6180XA1 for TT_Mxx
Embed:
(wiki syntax)
Show/hide line numbers
VL6180X.cpp
00001 #include <VL6180X.h> 00002 //#include "dm_platform.h" 00003 #include "common_define.h" 00004 // Defines ///////////////////////////////////////////////////////////////////// 00005 00006 // The Arduino two-wire interface uses a 7-bit number for the address, 00007 // and sets the last bit correctly based on reads and writes 00008 #define ADDRESS_DEFAULT (0x29 << 1) 00009 00010 // RANGE_SCALER values for 1x, 2x, 3x scaling - see STSW-IMG003 core/src/vl6180x_api.c (ScalerLookUP[]) 00011 static uint16_t const ScalerValues[] = {0, 253, 127, 84}; 00012 00013 #define constrain(amt,low,high) ((amt)<=(low)?(low):((amt)>(high)?(high):(amt))) 00014 // Constructors //////////////////////////////////////////////////////////////// 00015 00016 VL6180X::VL6180X(I2C *_i2c) 00017 : address(ADDRESS_DEFAULT) 00018 , scaling(0) 00019 , ptp_offset(0) 00020 , io_timeout(0) // no timeout 00021 , did_timeout(false) 00022 { 00023 i2c = _i2c; 00024 //configureDefault(); 00025 } 00026 00027 // Public Methods ////////////////////////////////////////////////////////////// 00028 00029 void VL6180X::setAddress(uint8_t new_addr) 00030 { 00031 writeReg(I2C_SLAVE__DEVICE_ADDRESS, new_addr & 0x7F); 00032 address = new_addr; 00033 } 00034 00035 // Initialize sensor with settings from ST application note AN4545, section 9 - 00036 // "Mandatory : private registers" 00037 void VL6180X::init() 00038 { 00039 // Store part-to-part range offset so it can be adjusted if scaling is changed 00040 ptp_offset = readReg(SYSRANGE__PART_TO_PART_RANGE_OFFSET); 00041 00042 if (readReg(SYSTEM__FRESH_OUT_OF_RESET) == 1) 00043 { 00044 scaling = 1; 00045 00046 writeReg(0x207, 0x01); 00047 writeReg(0x208, 0x01); 00048 writeReg(0x096, 0x00); 00049 writeReg(0x097, 0xFD); // RANGE_SCALER = 253 00050 writeReg(0x0E3, 0x00); 00051 writeReg(0x0E4, 0x04); 00052 writeReg(0x0E5, 0x02); 00053 writeReg(0x0E6, 0x01); 00054 writeReg(0x0E7, 0x03); 00055 writeReg(0x0F5, 0x02); 00056 writeReg(0x0D9, 0x05); 00057 writeReg(0x0DB, 0xCE); 00058 writeReg(0x0DC, 0x03); 00059 writeReg(0x0DD, 0xF8); 00060 writeReg(0x09F, 0x00); 00061 writeReg(0x0A3, 0x3C); 00062 writeReg(0x0B7, 0x00); 00063 writeReg(0x0BB, 0x3C); 00064 writeReg(0x0B2, 0x09); 00065 writeReg(0x0CA, 0x09); 00066 writeReg(0x198, 0x01); 00067 writeReg(0x1B0, 0x17); 00068 writeReg(0x1AD, 0x00); 00069 writeReg(0x0FF, 0x05); 00070 writeReg(0x100, 0x05); 00071 writeReg(0x199, 0x05); 00072 writeReg(0x1A6, 0x1B); 00073 writeReg(0x1AC, 0x3E); 00074 writeReg(0x1A7, 0x1F); 00075 writeReg(0x030, 0x00); 00076 00077 writeReg(SYSTEM__FRESH_OUT_OF_RESET, 0); 00078 } 00079 else 00080 { 00081 // Sensor has already been initialized, so try to get scaling settings by 00082 // reading registers. 00083 00084 uint16_t s = readReg16Bit(RANGE_SCALER); 00085 00086 if (s == ScalerValues[3]) { scaling = 3; } 00087 else if (s == ScalerValues[2]) { scaling = 2; } 00088 else { scaling = 1; } 00089 00090 // Adjust the part-to-part range offset value read earlier to account for 00091 // existing scaling. If the sensor was already in 2x or 3x scaling mode, 00092 // precision will be lost calculating the original (1x) offset, but this can 00093 // be resolved by resetting the sensor and Arduino again. 00094 ptp_offset *= scaling; 00095 } 00096 } 00097 00098 // Configure some settings for the sensor's default behavior from AN4545 - 00099 // "Recommended : Public registers" and "Optional: Public registers" 00100 // 00101 // Note that this function does not set up GPIO1 as an interrupt output as 00102 // suggested, though you can do so by calling: 00103 // writeReg(SYSTEM__MODE_GPIO1, 0x10); 00104 void VL6180X::configureDefault(void) 00105 { 00106 // "Recommended : Public registers" 00107 00108 // readout__averaging_sample_period = 48 00109 writeReg(READOUT__AVERAGING_SAMPLE_PERIOD, 0x30); 00110 00111 // sysals__analogue_gain_light = 6 (ALS gain = 1 nominal, actually 1.01 according to Table 14 in datasheet) 00112 writeReg(SYSALS__ANALOGUE_GAIN, 0x46); 00113 00114 // sysrange__vhv_repeat_rate = 255 (auto Very High Voltage temperature recalibration after every 255 range measurements) 00115 writeReg(SYSRANGE__VHV_REPEAT_RATE, 0xFF); 00116 00117 // sysals__integration_period = 99 (100 ms) 00118 // AN4545 incorrectly recommends writing to register 0x040; 0x63 should go in the lower byte, which is register 0x041. 00119 writeReg16Bit(SYSALS__INTEGRATION_PERIOD, 0x0063); 00120 00121 // sysrange__vhv_recalibrate = 1 (manually trigger a VHV recalibration) 00122 writeReg(SYSRANGE__VHV_RECALIBRATE, 0x01); 00123 00124 00125 // "Optional: Public registers" 00126 00127 // sysrange__intermeasurement_period = 9 (100 ms) 00128 writeReg(SYSRANGE__INTERMEASUREMENT_PERIOD, 0x09); 00129 00130 // sysals__intermeasurement_period = 49 (500 ms) 00131 writeReg(SYSALS__INTERMEASUREMENT_PERIOD, 0x31); 00132 00133 // als_int_mode = 4 (ALS new sample ready interrupt); range_int_mode = 4 (range new sample ready interrupt) 00134 writeReg(SYSTEM__INTERRUPT_CONFIG_GPIO, 0x24); 00135 00136 00137 // Reset other settings to power-on defaults 00138 00139 // sysrange__max_convergence_time = 49 (49 ms) 00140 writeReg(VL6180X::SYSRANGE__MAX_CONVERGENCE_TIME, 0x31); 00141 00142 // disable interleaved mode 00143 writeReg(INTERLEAVED_MODE__ENABLE, 0); 00144 00145 // reset range scaling factor to 1x 00146 setScaling(1); 00147 } 00148 00149 // Writes an 8-bit register 00150 void VL6180X::writeReg(uint16_t reg, uint8_t value) 00151 { 00152 i2cWriteForVL6180X(i2c,ADDRESS_DEFAULT,&value,reg,sizeof(value)); 00153 // Wire.beginTransmission(address); 00154 // Wire.write((reg >> 8) & 0xff); // reg high byte 00155 // Wire.write(reg & 0xff); // reg low byte 00156 // Wire.write(value); 00157 // last_status = Wire.endTransmission(); 00158 } 00159 00160 // Writes a 16-bit register 00161 void VL6180X::writeReg16Bit(uint16_t reg, uint16_t value) 00162 { 00163 uint8_t buffer[2]; 00164 buffer[0] = (value >> 8) & 0xff; 00165 buffer[1] = value & 0xff; 00166 i2cWriteForVL6180X(i2c,ADDRESS_DEFAULT,buffer,reg,sizeof(value)); 00167 // Wire.beginTransmission(address); 00168 // Wire.write((reg >> 8) & 0xff); // reg high byte 00169 // Wire.write(reg & 0xff); // reg low byte 00170 // Wire.write((value >> 8) & 0xff); // value high byte 00171 // Wire.write(value & 0xff); // value low byte 00172 // last_status = Wire.endTransmission(); 00173 } 00174 00175 // Writes a 32-bit register 00176 void VL6180X::writeReg32Bit(uint16_t reg, uint32_t value) 00177 { 00178 uint8_t buffer[4]; 00179 buffer[0] = (value >> 24) & 0xff; 00180 buffer[1] = (value >> 16)& 0xff; 00181 buffer[2] = (value >> 8)& 0xff; 00182 buffer[3] = value & 0xff; 00183 i2cWriteForVL6180X(i2c,ADDRESS_DEFAULT,buffer,reg,sizeof(value)); 00184 // Wire.beginTransmission(address); 00185 // Wire.write((reg >> 8) & 0xff); // reg high byte 00186 // Wire.write(reg & 0xff); // reg low byte 00187 // Wire.write((value >> 24) & 0xff); // value highest byte 00188 // Wire.write((value >> 16) & 0xff); 00189 // Wire.write((value >> 8) & 0xff); 00190 // Wire.write(value & 0xff); // value lowest byte 00191 // last_status = Wire.endTransmission(); 00192 } 00193 00194 // Reads an 8-bit register 00195 uint8_t VL6180X::readReg(uint16_t reg) 00196 { 00197 uint8_t value = 0xff; 00198 i2cReadForVL6180X(i2c,ADDRESS_DEFAULT,&value,reg,1); 00199 return value; 00200 00201 // Wire.beginTransmission(address); 00202 // Wire.write((reg >> 8) & 0xff); // reg high byte 00203 // Wire.write(reg & 0xff); // reg low byte 00204 // last_status = Wire.endTransmission(); 00205 00206 // Wire.requestFrom(address, (uint8_t)1); 00207 // value = Wire.read(); 00208 // Wire.endTransmission(); 00209 00210 // return value; 00211 } 00212 00213 // Reads a 16-bit register 00214 uint16_t VL6180X::readReg16Bit(uint16_t reg) 00215 { 00216 uint16_t value; 00217 i2cReadForVL6180X(i2c,ADDRESS_DEFAULT,(uint8_t *)&value,reg,sizeof(value)); 00218 return value; 00219 // uint16_t value; 00220 00221 // Wire.beginTransmission(address); 00222 // Wire.write((reg >> 8) & 0xff); // reg high byte 00223 // Wire.write(reg & 0xff); // reg low byte 00224 // last_status = Wire.endTransmission(); 00225 00226 // Wire.requestFrom(address, (uint8_t)2); 00227 // value = (uint16_t)Wire.read() << 8; // value high byte 00228 // value |= Wire.read(); // value low byte 00229 // Wire.endTransmission(); 00230 00231 // return value; 00232 } 00233 00234 // Reads a 32-bit register 00235 uint32_t VL6180X::readReg32Bit(uint16_t reg) 00236 { 00237 uint32_t value; 00238 i2cReadForVL6180X(i2c,ADDRESS_DEFAULT,(uint8_t *)&value,reg,sizeof(value)); 00239 return value; 00240 // uint32_t value; 00241 00242 // Wire.beginTransmission(address); 00243 // Wire.write((reg >> 8) & 0xff); // reg high byte 00244 // Wire.write(reg & 0xff); // reg low byte 00245 // last_status = Wire.endTransmission(); 00246 00247 // Wire.requestFrom(address, (uint8_t)4); 00248 // value = (uint32_t)Wire.read() << 24; // value highest byte 00249 // value |= (uint32_t)Wire.read() << 16; 00250 // value |= (uint16_t)Wire.read() << 8; 00251 // value |= Wire.read(); // value lowest byte 00252 // Wire.endTransmission(); 00253 00254 // return value; 00255 } 00256 00257 // Set range scaling factor. The sensor uses 1x scaling by default, giving range 00258 // measurements in units of mm. Increasing the scaling to 2x or 3x makes it give 00259 // raw values in units of 2 mm or 3 mm instead. In other words, a bigger scaling 00260 // factor increases the sensor's potential maximum range but reduces its 00261 // resolution. 00262 00263 // Implemented using ST's VL6180X API as a reference (STSW-IMG003); see 00264 // VL6180x_UpscaleSetScaling() in vl6180x_api.c. 00265 void VL6180X::setScaling(uint8_t new_scaling) 00266 { 00267 uint8_t const DefaultCrosstalkValidHeight = 20; // default value of SYSRANGE__CROSSTALK_VALID_HEIGHT 00268 00269 // do nothing if scaling value is invalid 00270 if (new_scaling < 1 || new_scaling > 3) { return; } 00271 00272 scaling = new_scaling; 00273 writeReg16Bit(RANGE_SCALER, ScalerValues[scaling]); 00274 00275 // apply scaling on part-to-part offset 00276 writeReg(VL6180X::SYSRANGE__PART_TO_PART_RANGE_OFFSET, ptp_offset / scaling); 00277 00278 // apply scaling on CrossTalkValidHeight 00279 writeReg(VL6180X::SYSRANGE__CROSSTALK_VALID_HEIGHT, DefaultCrosstalkValidHeight / scaling); 00280 00281 // This function does not apply scaling to RANGE_IGNORE_VALID_HEIGHT. 00282 00283 // enable early convergence estimate only at 1x scaling 00284 uint8_t rce = readReg(VL6180X::SYSRANGE__RANGE_CHECK_ENABLES); 00285 writeReg(VL6180X::SYSRANGE__RANGE_CHECK_ENABLES, (rce & 0xFE) | (scaling == 1)); 00286 } 00287 00288 // Performs a single-shot ranging measurement 00289 uint8_t VL6180X::readRangeSingle() 00290 { 00291 writeReg(SYSRANGE__START, 0x01); 00292 return readRangeContinuous(); 00293 } 00294 00295 // Performs a single-shot ambient light measurement 00296 uint16_t VL6180X::readAmbientSingle() 00297 { 00298 writeReg(SYSALS__START, 0x01); 00299 return readAmbientContinuous(); 00300 } 00301 00302 // Starts continuous ranging measurements with the given period in ms 00303 // (10 ms resolution; defaults to 100 ms if not specified). 00304 // 00305 // The period must be greater than the time it takes to perform a 00306 // measurement. See section 2.4.4 ("Continuous mode limits") in the datasheet 00307 // for details. 00308 void VL6180X::startRangeContinuous(uint16_t period) 00309 { 00310 int16_t period_reg = (int16_t)(period / 10) - 1; 00311 period_reg = constrain(period_reg, 0, 254); 00312 00313 writeReg(SYSRANGE__INTERMEASUREMENT_PERIOD, period_reg); 00314 writeReg(SYSRANGE__START, 0x03); 00315 } 00316 00317 // Starts continuous ambient light measurements with the given period in ms 00318 // (10 ms resolution; defaults to 500 ms if not specified). 00319 // 00320 // The period must be greater than the time it takes to perform a 00321 // measurement. See section 2.4.4 ("Continuous mode limits") in the datasheet 00322 // for details. 00323 void VL6180X::startAmbientContinuous(uint16_t period) 00324 { 00325 int16_t period_reg = (int16_t)(period / 10) - 1; 00326 period_reg = constrain(period_reg, 0, 254); 00327 00328 writeReg(SYSALS__INTERMEASUREMENT_PERIOD, period_reg); 00329 writeReg(SYSALS__START, 0x03); 00330 } 00331 00332 // Starts continuous interleaved measurements with the given period in ms 00333 // (10 ms resolution; defaults to 500 ms if not specified). In this mode, each 00334 // ambient light measurement is immediately followed by a range measurement. 00335 // 00336 // The datasheet recommends using this mode instead of running "range and ALS 00337 // continuous modes simultaneously (i.e. asynchronously)". 00338 // 00339 // The period must be greater than the time it takes to perform both 00340 // measurements. See section 2.4.4 ("Continuous mode limits") in the datasheet 00341 // for details. 00342 void VL6180X::startInterleavedContinuous(uint16_t period) 00343 { 00344 int16_t period_reg = (int16_t)(period / 10) - 1; 00345 period_reg = constrain(period_reg, 0, 254); 00346 00347 writeReg(INTERLEAVED_MODE__ENABLE, 1); 00348 writeReg(SYSALS__INTERMEASUREMENT_PERIOD, period_reg); 00349 writeReg(SYSALS__START, 0x03); 00350 } 00351 00352 // Stops continuous mode. This will actually start a single measurement of range 00353 // and/or ambient light if continuous mode is not active, so it's a good idea to 00354 // wait a few hundred ms after calling this function to let that complete 00355 // before starting continuous mode again or taking a reading. 00356 void VL6180X::stopContinuous() 00357 { 00358 00359 writeReg(SYSRANGE__START, 0x01); 00360 writeReg(SYSALS__START, 0x01); 00361 00362 writeReg(INTERLEAVED_MODE__ENABLE, 0); 00363 } 00364 00365 // Returns a range reading when continuous mode is activated 00366 // (readRangeSingle() also calls this function after starting a single-shot 00367 // range measurement) 00368 uint8_t VL6180X::readRangeContinuous() 00369 { 00370 uint16_t millis_start = millis(); 00371 while ((readReg(RESULT__INTERRUPT_STATUS_GPIO) & 0x04) == 0) 00372 { 00373 if (io_timeout > 0 && ((uint16_t)millis() - millis_start) > io_timeout) 00374 { 00375 did_timeout = true; 00376 return 255; 00377 } 00378 } 00379 00380 uint8_t range = readReg(RESULT__RANGE_VAL); 00381 writeReg(SYSTEM__INTERRUPT_CLEAR, 0x01); 00382 00383 return range; 00384 } 00385 00386 // Returns an ambient light reading when continuous mode is activated 00387 // (readAmbientSingle() also calls this function after starting a single-shot 00388 // ambient light measurement) 00389 uint16_t VL6180X::readAmbientContinuous() 00390 { 00391 uint16_t millis_start = millis(); 00392 while ((readReg(RESULT__INTERRUPT_STATUS_GPIO) & 0x20) == 0) 00393 { 00394 if (io_timeout > 0 && ((uint16_t)millis() - millis_start) > io_timeout) 00395 { 00396 did_timeout = true; 00397 return 0; 00398 } 00399 } 00400 writeReg(SYSTEM__FRESH_OUT_OF_RESET, 0); 00401 uint16_t ambient = readReg16Bit(RESULT__ALS_VAL); 00402 writeReg(SYSTEM__INTERRUPT_CLEAR, 0x02); 00403 return ambient; 00404 } 00405 00406 // Did a timeout occur in one of the read functions since the last call to 00407 // timeoutOccurred()? 00408 bool VL6180X::timeoutOccurred() 00409 { 00410 bool tmp = did_timeout; 00411 did_timeout = false; 00412 return tmp; 00413 } 00414
Generated on Tue Jul 12 2022 21:49:23 by 1.7.2