kl

Fork of VL6180x_lib by Robotique FIP

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers VL6180x.cpp Source File

VL6180x.cpp

00001 /******************************************************************************
00002  * SFE_VL6180x.cpp
00003  * Library for VL6180x time of flight range finder.
00004  * Casey Kuhns @ SparkFun Electronics
00005  * 10/29/2014
00006  * https://github.com/sparkfun/
00007  * 
00008  * The VL6180x 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 VL6180x 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  *  VL6180x 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 
00030 #include "VL6180x.h"
00031 
00032 VL6180x::VL6180x(PinName sda, PinName scl, uint8_t addr) : m_i2c(sda, scl), m_addr(addr) {}
00033 int VL6180x::VL6180xInit(void){
00034   uint8_t data; //for temp data storage
00035 
00036   data = VL6180x_getRegister(VL6180X_SYSTEM_FRESH_OUT_OF_RESET);
00037   wait_ms(50);
00038   if(data != 1) return VL6180x_FAILURE_RESET;
00039 
00040   //Required by datasheet
00041   //http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf
00042   VL6180x_setRegister(0x0207, 0x01);
00043   VL6180x_setRegister(0x0208, 0x01);
00044   VL6180x_setRegister(0x0096, 0x00);
00045   VL6180x_setRegister(0x0097, 0xfd); //lecture 25cm
00046   //VL6180x_setRegister(0x0097, 0x54); //lecture 50cm
00047   VL6180x_setRegister(0x00e3, 0x00);
00048   VL6180x_setRegister(0x00e4, 0x04);
00049   VL6180x_setRegister(0x00e5, 0x02);
00050   VL6180x_setRegister(0x00e6, 0x01);
00051   VL6180x_setRegister(0x00e7, 0x03);
00052   VL6180x_setRegister(0x00f5, 0x02);
00053   VL6180x_setRegister(0x00d9, 0x05);
00054   VL6180x_setRegister(0x00db, 0xce);
00055   VL6180x_setRegister(0x00dc, 0x03);
00056   VL6180x_setRegister(0x00dd, 0xf8);
00057   VL6180x_setRegister(0x009f, 0x00);
00058   VL6180x_setRegister(0x00a3, 0x3c); //lecture 25cm
00059   //VL6180x_setRegister(0x00a3, 0x28); //lecture 50cm
00060   VL6180x_setRegister(0x00b7, 0x00);
00061   VL6180x_setRegister(0x00bb, 0x3c); // lecture 25cm
00062   //VL6180x_setRegister(0x00bb, 0x28); // lecture 50cm
00063   VL6180x_setRegister(0x00b2, 0x09);
00064   VL6180x_setRegister(0x00ca, 0x09);  
00065   VL6180x_setRegister(0x0198, 0x01);
00066   VL6180x_setRegister(0x01b0, 0x17);
00067   VL6180x_setRegister(0x01ad, 0x00);
00068   VL6180x_setRegister(0x00ff, 0x05);
00069   VL6180x_setRegister(0x0100, 0x05);
00070   VL6180x_setRegister(0x0199, 0x05);
00071   VL6180x_setRegister(0x01a6, 0x1b);
00072   VL6180x_setRegister(0x01ac, 0x3e);
00073   VL6180x_setRegister(0x01a7, 0x1f);
00074   VL6180x_setRegister(0x0030, 0x00);
00075   return 0;
00076 }
00077 VL6180x::~VL6180x(void) {
00078 };
00079 
00080 void VL6180x::VL6180xDefautSettings(void){
00081   //Recommended settings from datasheet
00082   //http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf
00083 
00084   //Enable Interrupts on Conversion Complete (any source)
00085   VL6180x_setRegister(VL6180X_SYSTEM_INTERRUPT_CONFIG_GPIO, (4 << 3)|(4) ); // Set GPIO1 high when sample complete
00086 
00087 
00088   VL6180x_setRegister(VL6180X_SYSTEM_MODE_GPIO1, 0x10); // Set GPIO1 high when sample complete
00089   VL6180x_setRegister(VL6180X_READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); //Set Avg sample period
00090   VL6180x_setRegister(VL6180X_SYSALS_ANALOGUE_GAIN, 0x46); // Set the ALS gain
00091   VL6180x_setRegister(VL6180X_SYSRANGE_VHV_REPEAT_RATE, 0xFF); // Set auto calibration period (Max = 255)/(OFF = 0)
00092   VL6180x_setRegister(VL6180X_SYSALS_INTEGRATION_PERIOD, 0x63); // Set ALS integration time to 100ms
00093   VL6180x_setRegister(VL6180X_SYSRANGE_VHV_RECALIBRATE, 0x01); // perform a single temperature calibration
00094   //Optional settings from datasheet
00095   //http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf
00096   VL6180x_setRegister(VL6180X_SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); // Set default ranging inter-measurement period to 100ms
00097   VL6180x_setRegister(VL6180X_SYSALS_INTERMEASUREMENT_PERIOD, 0x0A); // Set default ALS inter-measurement period to 100ms
00098   VL6180x_setRegister(VL6180X_SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); // Configures interrupt on ‘New Sample Ready threshold event’ 
00099   //Additional settings defaults from community
00100   VL6180x_setRegister(VL6180X_SYSRANGE_MAX_CONVERGENCE_TIME, 0x32);
00101   VL6180x_setRegister(VL6180X_SYSRANGE_RANGE_CHECK_ENABLES, 0x10 | 0x01);
00102   VL6180x_setRegister16bit(VL6180X_SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, 0x7B );
00103   VL6180x_setRegister16bit(VL6180X_SYSALS_INTEGRATION_PERIOD, 0x64);
00104 
00105   VL6180x_setRegister(VL6180X_READOUT_AVERAGING_SAMPLE_PERIOD,0x30);
00106   VL6180x_setRegister(VL6180X_SYSALS_ANALOGUE_GAIN,0x40);
00107   VL6180x_setRegister(VL6180X_FIRMWARE_RESULT_SCALER,0x01);
00108 }
00109 void VL6180x::getIdentification(struct VL6180xIdentification *temp){
00110 
00111   temp->idModel =  VL6180x_getRegister(VL6180X_IDENTIFICATION_MODEL_ID);
00112   temp->idModelRevMajor = VL6180x_getRegister(VL6180X_IDENTIFICATION_MODEL_REV_MAJOR);
00113   temp->idModelRevMinor = VL6180x_getRegister(VL6180X_IDENTIFICATION_MODEL_REV_MINOR);
00114   temp->idModuleRevMajor = VL6180x_getRegister(VL6180X_IDENTIFICATION_MODULE_REV_MAJOR);
00115   temp->idModuleRevMinor = VL6180x_getRegister(VL6180X_IDENTIFICATION_MODULE_REV_MINOR);
00116 
00117   temp->idDate = VL6180x_getRegister16bit(VL6180X_IDENTIFICATION_DATE);
00118   temp->idTime = VL6180x_getRegister16bit(VL6180X_IDENTIFICATION_TIME);
00119 }
00120 
00121 
00122 uint8_t VL6180x::changeAddress(uint8_t old_address, uint8_t new_address){
00123   
00124   //NOTICE:  IT APPEARS THAT CHANGING THE ADDRESS IS NOT STORED IN NON-VOLATILE MEMORY
00125   // POWER CYCLING THE DEVICE REVERTS ADDRESS BACK TO 0X29
00126  
00127   if( old_address == new_address) return old_address;
00128   if( new_address > 127) return old_address;
00129    
00130    VL6180x_setRegister(VL6180X_I2C_SLAVE_DEVICE_ADDRESS, new_address);
00131    
00132    return VL6180x_getRegister(VL6180X_I2C_SLAVE_DEVICE_ADDRESS); 
00133 }
00134   
00135 
00136 
00137 uint8_t VL6180x::getDistance() {
00138   uint8_t distance;
00139   VL6180x_setRegister(VL6180X_SYSRANGE_START, 0x01); //Start Single shot mode
00140   wait_ms(10);
00141   distance = VL6180x_getRegister(VL6180X_RESULT_RANGE_VAL);
00142   VL6180x_setRegister(VL6180X_SYSTEM_INTERRUPT_CLEAR, 0x07);
00143   return distance;
00144 }
00145 
00146 float VL6180x::getAmbientLight(vl6180x_als_gain VL6180X_ALS_GAIN)
00147 {
00148   //First load in Gain we are using, do it everytime incase someone changes it on us.
00149   //Note: Upper nibble shoudl be set to 0x4 i.e. for ALS gain of 1.0 write 0x46
00150   VL6180x_setRegister(VL6180X_SYSALS_ANALOGUE_GAIN, (0x40 | VL6180X_ALS_GAIN)); // Set the ALS gain
00151 
00152   //Start ALS Measurement 
00153   VL6180x_setRegister(VL6180X_SYSALS_START, 0x01);
00154 
00155     wait_ms(100); //give it time... 
00156 
00157   VL6180x_setRegister(VL6180X_SYSTEM_INTERRUPT_CLEAR, 0x07);
00158 
00159   //Retrieve the Raw ALS value from the sensoe
00160   unsigned int alsRaw = VL6180x_getRegister16bit(VL6180X_RESULT_ALS_VAL);
00161   
00162   //Get Integration Period for calculation, we do this everytime incase someone changes it on us.
00163   unsigned int alsIntegrationPeriodRaw = VL6180x_getRegister16bit(VL6180X_SYSALS_INTEGRATION_PERIOD);
00164   
00165   float alsIntegrationPeriod = 100.0 / alsIntegrationPeriodRaw ;
00166 
00167   //Calculate actual LUX from Appnotes
00168 
00169   float alsGain = 0.0;
00170   
00171   switch (VL6180X_ALS_GAIN){
00172     case GAIN_20: alsGain = 20.0; break;
00173     case GAIN_10: alsGain = 10.32; break;
00174     case GAIN_5: alsGain = 5.21; break;
00175     case GAIN_2_5: alsGain = 2.60; break;
00176     case GAIN_1_67: alsGain = 1.72; break;
00177     case GAIN_1_25: alsGain = 1.28; break;
00178     case GAIN_1: alsGain = 1.01; break;
00179     case GAIN_40: alsGain = 40.0; break;
00180   }
00181 
00182 //Calculate LUX from formula in AppNotes
00183   
00184   float alsCalculated = (float)0.32 * ((float)alsRaw / alsGain) * alsIntegrationPeriod;
00185 
00186   return alsCalculated;
00187 }
00188 
00189 // --- Private Functions --- //
00190 
00191 uint8_t VL6180x::VL6180x_getRegister(uint16_t registerAddr)
00192 {
00193   uint8_t data;
00194   char data_write[2];
00195   char data_read[1];
00196   data_write[0] = (registerAddr >> 8) & 0xFF; //MSB of register address 
00197   data_write[1] = registerAddr & 0xFF; //LSB of register address 
00198   m_i2c.write(m_addr, data_write, 2,0); 
00199   m_i2c.read(m_addr,data_read,1,1);
00200   //Read Data from selected register
00201   data=data_read[0];
00202   return data;
00203 }
00204 
00205 uint16_t VL6180x::VL6180x_getRegister16bit(uint16_t registerAddr)
00206 {
00207   uint8_t data_low;
00208   uint8_t data_high;
00209   uint16_t data;
00210 
00211   char data_write[2];
00212   char data_read[2];
00213   data_write[0] = (registerAddr >> 8) & 0xFF; //MSB of register address 
00214   data_write[1] = registerAddr & 0xFF; //LSB of register address 
00215   m_i2c.write(m_addr, data_write, 2,0); 
00216   m_i2c.read(m_addr,data_read,2,1);
00217   data_high = data_read[0]; //Read Data from selected register
00218   data_low = data_read[1]; //Read Data from selected register
00219   data = (data_high << 8)|data_low;
00220 
00221   return data;
00222 }
00223 
00224 void VL6180x::VL6180x_setRegister(uint16_t registerAddr, uint8_t data)
00225 {
00226     char data_write[3];
00227     data_write[0] = (registerAddr >> 8) & 0xFF; //MSB of register address 
00228     data_write[1] = registerAddr & 0xFF; //LSB of register address 
00229     data_write[2] = data & 0xFF; 
00230     m_i2c.write(m_addr, data_write, 3); 
00231 }
00232 
00233 void VL6180x::VL6180x_setRegister16bit(uint16_t registerAddr, uint16_t data)
00234 {
00235     char data_write[4];
00236     data_write[0] = (registerAddr >> 8) & 0xFF; //MSB of register address 
00237     data_write[1] = registerAddr & 0xFF; //LSB of register address 
00238     data_write[2] = (data >> 8) & 0xFF;
00239     data_write[3] = data & 0xFF; 
00240     m_i2c.write(m_addr, data_write, 4); 
00241 }