w m / Mbed 2 deprecated DISTANCE_PROJECT1

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers VL6180.cpp Source File

VL6180.cpp

00001 /******************************************************************************
00002  * SFE_VL6180.cpp
00003  * Library for VL6180 time of flight range finder.
00004  * Casey Kuhns @ SparkFun Electronics
00005  * 10/29/2014
00006  * https://github.com/sparkfun/
00007  *
00008  * The VL6180 by ST micro is a time of flight range finder that
00009  * uses pulsed IR light to determine distances from object at close
00010  * range.  The average range of a sensor is between 0-200mm
00011  *
00012  * In this file are the functions in the VL6180 class
00013  *
00014  * Resources:
00015  * This library uses the Arduino Wire.h to complete I2C transactions.
00016  *
00017  * Development environment specifics:
00018  *  IDE: Arduino 1.0.5
00019  *  Hardware Platform: Arduino Pro 3.3V/8MHz
00020  *  VL6180 Breakout Version: 1.0
00021  *
00022  *
00023  * This code is beerware. If you see me (or any other SparkFun employee) at the
00024  * local pub, and you've found our code helpful, please buy us a round!
00025  *
00026  * Distributed as-is; no warranty is given.
00027  ******************************************************************************/
00028 
00029 #include "VL6180.h"
00030 
00031 //
00032 // Constructors
00033 //
00034 VL6180::VL6180(PinName sda, PinName scl)  : i2c(sda, scl)
00035 {
00036     VL6180_i2cAddress = VL6180_DEF_ADDR;
00037 }
00038 
00039 VL6180::VL6180(PinName sda, PinName scl, int i2cAddress)  : i2c(sda, scl)
00040 {
00041     VL6180_i2cAddress = i2cAddress;
00042     VL6180_error_no = 0;
00043 }
00044 //
00045 // destructor
00046 //
00047 VL6180::~VL6180()
00048 {
00049 }
00050 
00051 int8_t VL6180::VL6180_Init(void)
00052 {
00053     uint8_t data; //for temp data storage
00054 
00055     data = VL6180_getRegister(VL6180_SYSTEM_FRESH_OUT_OF_RESET);
00056 
00057     if(data != 1) return VL6180_FAILURE_RESET;
00058 
00059     //Required by datasheet
00060     //http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf
00061     VL6180_setRegister(0x0207, 0x01);
00062     VL6180_setRegister(0x0208, 0x01);
00063     VL6180_setRegister(0x0096, 0x00);
00064     VL6180_setRegister(0x0097, 0xfd);
00065     VL6180_setRegister(0x00e3, 0x00);
00066     VL6180_setRegister(0x00e4, 0x04);
00067     VL6180_setRegister(0x00e5, 0x02);
00068     VL6180_setRegister(0x00e6, 0x01);
00069     VL6180_setRegister(0x00e7, 0x03);
00070     VL6180_setRegister(0x00f5, 0x02);
00071     VL6180_setRegister(0x00d9, 0x05);
00072     VL6180_setRegister(0x00db, 0xce);
00073     VL6180_setRegister(0x00dc, 0x03);
00074     VL6180_setRegister(0x00dd, 0xf8);
00075     VL6180_setRegister(0x009f, 0x00);
00076     VL6180_setRegister(0x00a3, 0x3c);
00077     VL6180_setRegister(0x00b7, 0x00);
00078     VL6180_setRegister(0x00bb, 0x3c);
00079     VL6180_setRegister(0x00b2, 0x09);
00080     VL6180_setRegister(0x00ca, 0x09);
00081     VL6180_setRegister(0x0198, 0x01);
00082     VL6180_setRegister(0x01b0, 0x17);
00083     VL6180_setRegister(0x01ad, 0x00);
00084     VL6180_setRegister(0x00ff, 0x05);
00085     VL6180_setRegister(0x0100, 0x05);
00086     VL6180_setRegister(0x0199, 0x05);
00087     VL6180_setRegister(0x01a6, 0x1b);
00088     VL6180_setRegister(0x01ac, 0x3e);
00089     VL6180_setRegister(0x01a7, 0x1f);
00090     VL6180_setRegister(0x0030, 0x00);
00091     
00092     VL6180_setRegister(VL6180_SYSTEM_FRESH_OUT_OF_RESET, 0x00);
00093     return 0;
00094 }
00095 
00096 void VL6180::VL6180_DefautSettings(void)
00097 {
00098     //Recommended settings from datasheet
00099     //http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf
00100 
00101     //Enable Interrupts on Conversion Complete (any source)
00102     VL6180_setRegister(VL6180_SYSTEM_INTERRUPT_CONFIG_GPIO, (4 << 3)|(4) ); // Set GPIO1 high when sample complete
00103 
00104 
00105     VL6180_setRegister(VL6180_SYSTEM_MODE_GPIO1, 0x10); // Set GPIO1 high when sample complete
00106     VL6180_setRegister(VL6180_READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); //Set Avg sample period
00107     VL6180_setRegister(VL6180_SYSALS_ANALOGUE_GAIN, 0x46); // Set the ALS gain
00108     VL6180_setRegister(VL6180_SYSRANGE_VHV_REPEAT_RATE, 0xFF); // Set auto calibration period (Max = 255)/(OFF = 0)
00109     VL6180_setRegister(VL6180_SYSALS_INTEGRATION_PERIOD, 0x63); // Set ALS integration time to 100ms
00110     VL6180_setRegister(VL6180_SYSRANGE_VHV_RECALIBRATE, 0x01); // perform a single temperature calibration
00111     //Optional settings from datasheet
00112     //http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf
00113     VL6180_setRegister(VL6180_SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); // Set default ranging inter-measurement period to 100ms
00114     VL6180_setRegister(VL6180_SYSALS_INTERMEASUREMENT_PERIOD, 0x0A); // Set default ALS inter-measurement period to 100ms
00115     VL6180_setRegister(VL6180_SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); // Configures interrupt on 鈥楴ew Sample Ready threshold event鈥?
00116     //Additional settings defaults from community
00117     VL6180_setRegister(VL6180_SYSRANGE_MAX_CONVERGENCE_TIME, 0x32);
00118     VL6180_setRegister(VL6180_SYSRANGE_RANGE_CHECK_ENABLES, 0x10 | 0x01);
00119     VL6180_setRegister16bit(VL6180_SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, 0x7B );
00120     VL6180_setRegister16bit(VL6180_SYSALS_INTEGRATION_PERIOD, 0x64);
00121 
00122     VL6180_setRegister(VL6180_READOUT_AVERAGING_SAMPLE_PERIOD,0x30);
00123     VL6180_setRegister(VL6180_SYSALS_ANALOGUE_GAIN,0x40);
00124     VL6180_setRegister(VL6180_FIRMWARE_RESULT_SCALER,0x01);
00125 }
00126 void VL6180::getIdentification(struct VL6180Identification *temp)
00127 {
00128 
00129     temp->idModel =  VL6180_getRegister(VL6180_IDENTIFICATION_MODEL_ID);
00130     temp->idModelRevMajor = VL6180_getRegister(VL6180_IDENTIFICATION_MODEL_REV_MAJOR);
00131     temp->idModelRevMinor = VL6180_getRegister(VL6180_IDENTIFICATION_MODEL_REV_MINOR);
00132     temp->idModuleRevMajor = VL6180_getRegister(VL6180_IDENTIFICATION_MODULE_REV_MAJOR);
00133     temp->idModuleRevMinor = VL6180_getRegister(VL6180_IDENTIFICATION_MODULE_REV_MINOR);
00134 
00135     temp->idDate = VL6180_getRegister16bit(VL6180_IDENTIFICATION_DATE);
00136     temp->idTime = VL6180_getRegister16bit(VL6180_IDENTIFICATION_TIME);
00137 }
00138 
00139 
00140 uint8_t VL6180::changeAddress(uint8_t old_address, uint8_t new_address)
00141 {
00142 
00143     //NOTICE:  IT APPEARS THAT CHANGING THE ADDRESS IS NOT STORED IN NON-VOLATILE MEMORY
00144     // POWER CYCLING THE DEVICE REVERTS ADDRESS BACK TO 0X29
00145 
00146     if( old_address == new_address) return old_address;
00147     if( new_address > 127) return old_address;
00148 
00149     VL6180_setRegister(VL6180_I2C_SLAVE_DEVICE_ADDRESS, new_address);
00150 
00151     return VL6180_getRegister(VL6180_I2C_SLAVE_DEVICE_ADDRESS);
00152 }
00153 
00154 
00155 
00156 uint8_t VL6180::getDistance()
00157 {
00158     VL6180_setRegister(VL6180_SYSRANGE_START, 0x01); //Start Single shot mode
00159     wait(0.01);    // 10mS
00160     return VL6180_getRegister(VL6180_RESULT_RANGE_VAL);
00161 //    VL6180_setRegister(VL6180_SYSTEM_INTERRUPT_CLEAR, 0x07);
00162 //    return distance;
00163 }
00164 
00165 float VL6180::getAmbientLight(VL6180_als_gain VL6180_ALS_GAIN)
00166 {
00167     //First load in Gain we are using, do it everytime incase someone changes it on us.
00168     //Note: Upper nibble shoudl be set to 0x4 i.e. for ALS gain of 1.0 write 0x46
00169     VL6180_setRegister(VL6180_SYSALS_ANALOGUE_GAIN, (0x40 | VL6180_ALS_GAIN)); // Set the ALS gain
00170 
00171     //Start ALS Measurement
00172     VL6180_setRegister(VL6180_SYSALS_START, 0x01);
00173 
00174     wait(0.1); //100Ms
00175 
00176     VL6180_setRegister(VL6180_SYSTEM_INTERRUPT_CLEAR, 0x07);
00177 
00178     //Retrieve the Raw ALS value from the sensoe
00179     unsigned int alsRaw = VL6180_getRegister16bit(VL6180_RESULT_ALS_VAL);
00180 
00181     //Get Integration Period for calculation, we do this everytime incase someone changes it on us.
00182     unsigned int alsIntegrationPeriodRaw = VL6180_getRegister16bit(VL6180_SYSALS_INTEGRATION_PERIOD);
00183 
00184     float alsIntegrationPeriod = 100.0 / alsIntegrationPeriodRaw ;
00185 
00186     //Calculate actual LUX from Appnotes
00187 
00188     float alsGain = 0.0;
00189 
00190     switch (VL6180_ALS_GAIN) {
00191         case GAIN_20:
00192             alsGain = 20.0;
00193             break;
00194         case GAIN_10:
00195             alsGain = 10.32;
00196             break;
00197         case GAIN_5:
00198             alsGain = 5.21;
00199             break;
00200         case GAIN_2_5:
00201             alsGain = 2.60;
00202             break;
00203         case GAIN_1_67:
00204             alsGain = 1.72;
00205             break;
00206         case GAIN_1_25:
00207             alsGain = 1.28;
00208             break;
00209         case GAIN_1:
00210             alsGain = 1.01;
00211             break;
00212         case GAIN_40:
00213             alsGain = 40.0;
00214             break;
00215     }
00216 
00217 //Calculate LUX from formula in AppNotes
00218 
00219     float alsCalculated = (float)0.32 * ((float)alsRaw / alsGain) * alsIntegrationPeriod;
00220 
00221     return alsCalculated;
00222 }
00223 
00224 // --- Private Functions --- //
00225 
00226 uint8_t VL6180::VL6180_getRegister(uint16_t reg_address)
00227 {
00228     char data[2];
00229 
00230     data[0] = (reg_address >> 8) & 0xFF; //MSB of register address
00231     data[1] = reg_address & 0xFF; //LSB of register address
00232     VL6180_error_no = i2c.write(VL6180_i2cAddress, data, 2);
00233     VL6180_error_no = i2c.read(VL6180_i2cAddress, data, 1, false);
00234     return data[0];
00235 }
00236 
00237 uint16_t VL6180::VL6180_getRegister16bit(uint16_t reg_address)
00238 {
00239     char data[2];
00240 
00241     data[0] = (reg_address >> 8) & 0xFF; //MSB of register address
00242     data[1] = reg_address & 0xFF; //LSB of register address
00243     VL6180_error_no = i2c.write(VL6180_i2cAddress, data, 2);
00244     VL6180_error_no = i2c.read(VL6180_i2cAddress, data, 2, false);
00245     return (data[0] + ((data[1] << 8) & 0xFF00));
00246 }
00247 
00248 void VL6180::VL6180_setRegister(uint16_t reg_address, uint8_t value)
00249 {
00250     char  data[3];
00251 
00252     data[0] = (reg_address >> 8) & 0xFF;    //MSB of register address
00253     data[1] = reg_address & 0xFF;           //LSB of register address
00254     data[2] = value;
00255     VL6180_error_no = VL6180_error_no = i2c.write(VL6180_i2cAddress, data, 3);
00256 }
00257 
00258 void VL6180::VL6180_setRegister16bit(uint16_t reg_address, uint16_t value)
00259 {
00260     char  data[4];
00261 
00262     data[0] = (reg_address >> 8) & 0xFF;    //MSB of register address
00263     data[1] = reg_address & 0xFF;           //LSB of register address
00264     data[2] = value & 0xFF;
00265     data[3] = ((value >> 8) & 0xFF);
00266     VL6180_error_no = VL6180_error_no = i2c.write(VL6180_i2cAddress, data, 4);
00267 }
00268 
00269 int VL6180::writeSingleRegister( uint16_t reg_address, uint8_t data )
00270 {
00271 
00272     char data_write[3];
00273     data_write[0] = (reg_address >> 8) & 0xFF; //MSB of register address
00274     data_write[1] = reg_address & 0xFF; //LSB of register address
00275     data_write[2] = data & 0xFF;
00276     return i2c.write(VL6180_DEF_ADDR, data_write, 3);
00277 
00278 //   char tx[2] = { address | 160, data }; //0d160 = 0b10100000
00279 //   int ack = i2c.write( SLAVE_ADDRESS << 1, tx, 2 );
00280 //   return ack;
00281 }
00282