PrinceNai
Joined: 31 Oct 2016 Posts: 471 Location: Montenegro
|
vl6180 library, single shot mode |
Posted: Thu Jul 18, 2024 9:24 am |
|
|
Hi,
vl6180 library, single shot mode.
vl6180.h
Code: |
#define VL6180_address 0x52
unsigned int8 VL6180_distance;
// ****************** VL6180 FUNCTIONS ************************
// ************************************************************
// *********** READ ONE BYTE OF DATA FROM VL6180 **************
// reads 8 bits from register 'reg_addr' that has a 16 bit address
// Split 16-bit register address into two bytes and write
// the address + read one byte of data via I2C
char VL6180_ReadByte(unsigned int16 reg_addr)
{
char data_read;
int8 reg_address_MSB = make8(reg_addr, 1); // Make MSB of reg_addr
int8 reg_address_LSB = make8(reg_addr, 0); // Make LSB of reg_addr. Could be done directly at i2c_write().
I2C_Start();
I2C_Write(VL6180_address); // call VL6180
I2C_Write(reg_address_MSB); // send MSB of register address
I2C_Write(reg_address_LSB); // send LSB of register address
I2C_Start(); // repeat start and turn the direction of the transfer
I2C_Write(VL6180_address + 1); // send read address
data_read = I2C_Read(0); // read one byte of data, send NACK
I2C_Stop(); // stop I2C
return data_read; // and return data to the caller
}
// *********** WRITE ONE BYTE OF DATA TO VL6180 ***************
// Split 16-bit register address into two bytes and write
// the address + one byte of data via I2C
void VL6180_WriteByte(unsigned int16 reg_addr, char data) {
int8 reg_address_MSB = make8(reg_addr,1); // MSB of register address
int8 reg_address_LSB = make8(reg_addr,0); // LSB of register address. Could be done directly at i2c_write().
I2C_Start();
I2C_Write(VL6180_address); //
I2C_Write(reg_address_MSB); // write MSB of register address
I2C_Write(reg_address_LSB); // write LSB of register address
I2C_Write(data); // write data to the selected register
I2C_Stop();
}
// ****************** INIT VL6180 *****************************
void Init_VL6180 (void){
int8 reset;
reset = VL6180_ReadByte(0x016);
if (reset == 1){ // check to see if VL6180 has been initialised already
// if not, load
// sensor calibration values, should be loaded on any sensor reset or power-up
// Mandatory : private registers. Values are from the datasheet.
VL6180_WriteByte(0x0207, 0x01);
VL6180_WriteByte(0x0208, 0x01);
VL6180_WriteByte(0x0096, 0x00);
VL6180_WriteByte(0x0097, 0xfd);
VL6180_WriteByte(0x00e3, 0x00);
VL6180_WriteByte(0x00e4, 0x04);
VL6180_WriteByte(0x00e5, 0x02);
VL6180_WriteByte(0x00e6, 0x01);
VL6180_WriteByte(0x00e7, 0x03);
VL6180_WriteByte(0x00f5, 0x02);
VL6180_WriteByte(0x00db, 0xce);
VL6180_WriteByte(0x00dc, 0x03);
VL6180_WriteByte(0x00dd, 0xf8);
VL6180_WriteByte(0x009f, 0x00);
VL6180_WriteByte(0x00a3, 0x3c);
VL6180_WriteByte(0x00b7, 0x00);
VL6180_WriteByte(0x00bb, 0x3c);
VL6180_WriteByte(0x00b2, 0x09);
VL6180_WriteByte(0x00ca, 0x09);
VL6180_WriteByte(0x0198, 0x01);
VL6180_WriteByte(0x01b0, 0x17);
VL6180_WriteByte(0x01ad, 0x00);
VL6180_WriteByte(0x00ff, 0x05);
VL6180_WriteByte(0x0100, 0x05);
VL6180_WriteByte(0x0199, 0x05);
VL6180_WriteByte(0x01a6, 0x1b);
VL6180_WriteByte(0x01ac, 0x3e);
VL6180_WriteByte(0x01a7, 0x1f);
VL6180_WriteByte(0x0030, 0x00);
// Recommended : Public registers - See data sheet for more detail
VL6180_WriteByte(0x0011, 0x10); // Enables polling for 'New Sample ready' when measurement completes
VL6180_WriteByte(0x010a, 0x30); // Set the averaging sample period (compromise between lower noise and increased execution time)
VL6180_WriteByte(0x003f, 0x46); // Sets the light and dark gain (upper nibble). Dark gain should not be CHANGED.
VL6180_WriteByte(0x0031, 0xFF); // sets the # of range measurements after which auto calibration of system is performed
VL6180_WriteByte(0x0040, 0x63); // Set ALS integration time to 100ms
VL6180_WriteByte(0x002e, 0x01); // perform a single temperature calibration of the ranging sensor
//Optional: Public registers - See data sheet for more detail
VL6180_WriteByte(0x001b, 0x09); // Set default ranging inter-measurement period to 100ms
VL6180_WriteByte(0x003e, 0x31); // Set default ALS inter-measurement period to 500ms
VL6180_WriteByte(0x0014, 0x24); // Configures interrupt on 'New Sample Ready threshold event'
VL6180_WriteByte(0x016, 0x00); // change fresh out of set status to 0
}
}
///////////////////////////////////////////////////////////////
// Start a range measurement in single shot mode
///////////////////////////////////////////////////////////////
void VL6180_Start_Range() {
VL6180_WriteByte(0x018,0x01); // do one measurement
}
///////////////////////////////////////////////////////////////
// poll for new RANGE sample to be ready
///////////////////////////////////////////////////////////////
void VL6180_Poll_Range() {
int8 status;
int8 range_status;
status = VL6180_ReadByte(0x04f); // check the measurement status
range_status = status & 0x07;
while (range_status != 0x04) { // wait for new measurement ready status
status = VL6180_ReadByte(0x04f);
range_status = status & 0x07;
delay_ms(1); // (can be removed)
}
}
///////////////////////////////////////////////////////////////
// Read range result (mm)
///////////////////////////////////////////////////////////////
char VL6180_Read_Range() {
char range;
range = VL6180_ReadByte(0x062); // read and return distance in mm
return range;
}
///////////////////////////////////////////////////////////////
// clear VL6180 interrupts
///////////////////////////////////////////////////////////////
void VL6180_Clear_Interrupts() {
VL6180_WriteByte(0x015, 0x07); // clear interrupts
}
////////////////// END VL6180 FUNCTIONS ///////////////////////
|
Example program:
Code: |
// ************************************************************
// Sensor shows distances up to approx. 180mm, after that
// it returns 255 or Out of Range. Physical connections are
// only VCC, VDD, SCL, SDA. Shutdown pin is left floating
// (works on my module)
// ************************************************************
#include <18F46K22.h>
#device ADC=10
#FUSES NOWDT // No Watch Dog Timer
#FUSES DEBUG
#FUSES NOPUT // for compatibility with PICKIT3 debugging
#device ICD =TRUE
#use delay(internal=32000000)
#use rs232(baud = 19200, parity = N, UART1, bits = 8,stream = DEBUG, errors)
#use i2c(Master, Slow, sda = PIN_C4, scl = PIN_C3, force_hw, stream = I2C1)
// ********************* INCLUDES *****************************
#include <string.h>
#include "1306.h" // The OLED driver
#include "vl6180.h" // vl1680 driver
// ************************************************************
void main()
{
delay_ms(10); // OLED takes time to wake up. Maybe not this much time, but...
//now try to initialise OLED
OLED_commands(init_sequence,sizeof(init_sequence)); // initialise OLED
set = TRUE; // white on black text
size = NORMAL; // 21 characters in a row, 8 rows, total 168 chars
// size=LARGE; // large font, switches between showing 21*8 & 10*4 characters
OLED_CLS(); // clear the physical screen, go top left
printf(OLED_putc,"VL6180x\n\r");
delay_ms(1000);
OLED_CLS(); // clear the physical screen, go top left
Init_VL6180(); // load settings into VL6180X, must be done upon any reset
while(TRUE)
{
VL6180_Start_Range(); // start a single range measurement
VL6180_Poll_Range(); // poll the VL6180 till new range sample is ready
VL6180_distance = VL6180_Read_Range(); // read distance result in mm
VL6180_Clear_Interrupts(); // clear interrupts on VL6180
OLED_gotoxy(0,0); // go to appropriate position on OLED
if(VL6180_distance < 255){ // returned value of 255 means distance is out of range
fprintf(DEBUG, "%3u\r\n", VL6180_distance); // send distance measurement to pc by serial
printf(OLED_putc,"%3u \r\n", VL6180_distance);// display distance on OLED. Spaces are used to cover "Out of range" messages on OLED.
}
else{
fprintf(DEBUG, "Out of range"); // send out of range message to pc by serial
printf(OLED_putc, "Out of range"); // and to OLED
}
delay_ms(100);
} // while(TRUE)
} // main
|
If you don't have this OLED, simply remove all the parts of the code not needed. |
|