Difference between revisions of "GY-530 VL53L0X Laser Range Finder Distance Measurement Sensor Module"

From Wiki
Jump to: navigation, search
(Experimental Procedures for Arduino)
(Experimental Procedures for Arduino)
Line 93: Line 93:
 
<br>
 
<br>
 
'''Step 2:''' Compile and upload the code.
 
'''Step 2:''' Compile and upload the code.
 +
<per>
 +
//the original code by Ted Meyers
 +
//posted here: https://groups.google.com/d/msg/diyrovers/lc7NUZYuJOg/ICPrYNJGBgAJ
  
 +
#include <Wire.h>
 +
 +
#define VL53L0X_REG_IDENTIFICATION_MODEL_ID        0xc0
 +
#define VL53L0X_REG_IDENTIFICATION_REVISION_ID      0xc2
 +
#define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD  0x50
 +
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x70
 +
#define VL53L0X_REG_SYSRANGE_START                  0x00
 +
#define VL53L0X_REG_RESULT_INTERRUPT_STATUS        0x13
 +
#define VL53L0X_REG_RESULT_RANGE_STATUS            0x14
 +
#define address 0x29
 +
 +
byte gbuf[16];
 +
 +
void setup() {
 +
  // put your setup code here, to run once:
 +
  Wire.begin();        // join i2c bus (address optional for master)
 +
  Serial.begin(9600);  // start serial for output
 +
  Serial.println("VLX53LOX test started.");
 +
}
 +
 +
void loop() {
 +
  Serial.println("----- START TEST ----");
 +
  test();
 +
  Serial.println("----- END TEST ----");
 +
  Serial.println("");
 +
  delay(1000);
 +
}
 +
 +
void test() {
 +
  byte val1 = read_byte_data_at(VL53L0X_REG_IDENTIFICATION_REVISION_ID);
 +
  Serial.print("Revision ID: "); Serial.println(val1);
 +
 +
  val1 = read_byte_data_at(VL53L0X_REG_IDENTIFICATION_MODEL_ID);
 +
  Serial.print("Device ID: "); Serial.println(val1);
 +
 +
  val1 = read_byte_data_at(VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD);
 +
  Serial.print("PRE_RANGE_CONFIG_VCSEL_PERIOD="); Serial.println(val1);
 +
  Serial.print(" decode: "); Serial.println(VL53L0X_decode_vcsel_period(val1));
 +
 +
  val1 = read_byte_data_at(VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD);
 +
  Serial.print("FINAL_RANGE_CONFIG_VCSEL_PERIOD="); Serial.println(val1);
 +
  Serial.print(" decode: "); Serial.println(VL53L0X_decode_vcsel_period(val1));
 +
 +
  write_byte_data_at(VL53L0X_REG_SYSRANGE_START, 0x01);
 +
 +
  byte val = 0;
 +
  int cnt = 0;
 +
  while (cnt < 100) { // 1 second waiting time max
 +
    delay(10);
 +
    val = read_byte_data_at(VL53L0X_REG_RESULT_RANGE_STATUS);
 +
    if (val & 0x01) break;
 +
    cnt++;
 +
  }
 +
  if (val & 0x01) Serial.println("ready"); else Serial.println("not ready");
 +
 +
  read_block_data_at(0x14, 12);
 +
  uint16_t acnt = makeuint16(gbuf[7], gbuf[6]);
 +
  uint16_t scnt = makeuint16(gbuf[9], gbuf[8]);
 +
  uint16_t dist = makeuint16(gbuf[11], gbuf[10]);
 +
  byte DeviceRangeStatusInternal = ((gbuf[0] & 0x78) >> 3);
 +
 +
  Serial.print("ambient count: "); Serial.println(acnt);
 +
  Serial.print("signal count: ");  Serial.println(scnt);
 +
  Serial.print("distance ");      Serial.println(dist);
 +
  Serial.print("status: ");        Serial.println(DeviceRangeStatusInternal);
 +
}
 +
 +
uint16_t bswap(byte b[]) {
 +
  // Big Endian unsigned short to little endian unsigned short
 +
  uint16_t val = ((b[0] << 8) & b[1]);
 +
  return val;
 +
}
 +
 +
uint16_t makeuint16(int lsb, int msb) {
 +
    return ((msb & 0xFF) << 8) | (lsb & 0xFF);
 +
}
 +
 +
void write_byte_data(byte data) {
 +
  Wire.beginTransmission(address);
 +
  Wire.write(data);
 +
  Wire.endTransmission();
 +
}
 +
 +
void write_byte_data_at(byte reg, byte data) {
 +
  // write data word at address and register
 +
  Wire.beginTransmission(address);
 +
  Wire.write(reg);
 +
  Wire.write(data);
 +
  Wire.endTransmission();
 +
}
 +
 +
void write_word_data_at(byte reg, uint16_t data) {
 +
  // write data word at address and register
 +
  byte b0 = (data &0xFF);
 +
  byte b1 = ((data >> 8) && 0xFF);
 +
   
 +
  Wire.beginTransmission(address);
 +
  Wire.write(reg);
 +
  Wire.write(b0);
 +
  Wire.write(b1);
 +
  Wire.endTransmission();
 +
}
 +
 +
byte read_byte_data() {
 +
  Wire.requestFrom(address, 1);
 +
  while (Wire.available() < 1) delay(1);
 +
  byte b = Wire.read();
 +
  return b;
 +
}
 +
 +
byte read_byte_data_at(byte reg) {
 +
  //write_byte_data((byte)0x00);
 +
  write_byte_data(reg);
 +
  Wire.requestFrom(address, 1);
 +
  while (Wire.available() < 1) delay(1);
 +
  byte b = Wire.read();
 +
  return b;
 +
}
 +
 +
uint16_t read_word_data_at(byte reg) {
 +
  write_byte_data(reg);
 +
  Wire.requestFrom(address, 2);
 +
  while (Wire.available() < 2) delay(1);
 +
  gbuf[0] = Wire.read();
 +
  gbuf[1] = Wire.read();
 +
  return bswap(gbuf);
 +
}
 +
 +
void read_block_data_at(byte reg, int sz) {
 +
  int i = 0;
 +
  write_byte_data(reg);
 +
  Wire.requestFrom(address, sz);
 +
  for (i=0; i<sz; i++) {
 +
    while (Wire.available() < 1) delay(1);
 +
    gbuf[i] = Wire.read();
 +
  }
 +
}
 +
 +
 +
uint16_t VL53L0X_decode_vcsel_period(short vcsel_period_reg) {
 +
  // Converts the encoded VCSEL period register value into the real
 +
  // period in PLL clocks
 +
  uint16_t vcsel_period_pclks = (vcsel_period_reg + 1) << 1;
 +
  return vcsel_period_pclks;
 +
}
 +
 +
</per>
 
[[File:GY-530_6.jpg]]
 
[[File:GY-530_6.jpg]]

Revision as of 03:55, 16 October 2019

Introduction

GY-530 1.jpg GY-530 2.jpg
The GY-530 sensor has the VL53L0X sensor on board, with power management IC on board, the module can accept power arrange from 2.8V to 5V.

The VL53L0X is a new generation Time-of-Flight (ToF) laser-ranging module housed in the smallest package on the market today, providing accurate distance measurement whatever the target reflectances unlike conventional technologies. It can measure absolute distances up to 2m, set a new benchmark in ranging performance levels, and open the door to various new applications.
The VL53L0X integrates a leading-edge SPAD array (Single Photon Avalanche Diodes) and embeds ST’s second generation FlightSenseTM patented technology.
The VL53L0X’s 940nm VCSEL emitter (Vertical Cavity Surface-Emitting Laser), is totally invisible to the human eye, coupled with internal physical infrared filters, and it enables longer ranging distance, higher immunity to ambient light and better robustness to cover-glass optical cross-talk.

Applications

  1. User detection for Personal Computers/Laptops/Tablets and IoT (Energy saving).
  2. Robotics (obstacle detection).
  3. White goods (hand detection in automatic faucets, soap dispensers etc...)
  4. 1D gesture recognition.
  5. Laser assisted Auto-Focus. Enhances and speeds-up camera AF system performance, especially in difficult scenes (low light levels, low contrast) or fast moving video mode.

Features

  1. Fully integrated miniature module
  2. – 940nm Laser VCSEL
    – VCSEL driver
    – Ranging sensor with advanced embedded micro controller
    – 4.4 x 2.4 x 1.0mm

  3. Fast, accurate distance ranging
  4. – Measures absolute range up to 2m
    – Reported range is independent of the target reflectance
    – Operates in high infrared ambient light levels
    – Advanced embedded optical cross-talk compensation to simplify cover glass selection

  5. Eye safe
  6. – Class 1 laser device compliant with latest standard IEC 60825-1:2014 - 3rd edition

  7. Easy integration– Single reflowable component
  8. – No additional optics
    – Single power supply
    – I2C interface for device control and data transfer
    – Xshutdown (Reset) and interrupt GPIO
    – Programmable I2C address


Introduction of Pins

Introduction of Pins
VIN Connected to the anode of the power supply
GND Connected to the ground wire
SCL 12C SCK
SDA I2C serial data wire
XSHUT Reset pins only available under low level
GPIO1 Interrupt pins

Working Principle

GY-530 3.jpg Note:
Capacitors on external supply AVDD should be placed as close as possible to the AVDDVCSEL and AVSSVCSEL module pins.

Note:
External pull-up resistors values can be found in I2C-bus specification. Pull-up are typically fit only once per bus, near the host. Recommended values for pull-up resistors for an AVDD of 2.8V and 400KHz I2C clock would be 1.5k to 2k Ohms.

Note:
XSHUT pin must always be driven to avoid leakage current. Pull-up is needed if the host state is not known. XSHUT is needed to use HW standby mode (no I2C comm).

Note:
XSHUT and GPIO1 pull up recommended values are 10k Ohms. Note: GPIO1 to be left unconnected if not used.

GY-530 4.jpg

Experimental Procedures for Arduino

Step 1: Connect the circuit:
GY-530 5.jpg
Step 2: Compile and upload the code. <per> //the original code by Ted Meyers //posted here: https://groups.google.com/d/msg/diyrovers/lc7NUZYuJOg/ICPrYNJGBgAJ

  1. include <Wire.h>
  1. define VL53L0X_REG_IDENTIFICATION_MODEL_ID 0xc0
  2. define VL53L0X_REG_IDENTIFICATION_REVISION_ID 0xc2
  3. define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD 0x50
  4. define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x70
  5. define VL53L0X_REG_SYSRANGE_START 0x00
  6. define VL53L0X_REG_RESULT_INTERRUPT_STATUS 0x13
  7. define VL53L0X_REG_RESULT_RANGE_STATUS 0x14
  8. define address 0x29

byte gbuf[16];

void setup() {

 // put your setup code here, to run once:
 Wire.begin();        // join i2c bus (address optional for master)
 Serial.begin(9600);  // start serial for output
 Serial.println("VLX53LOX test started.");

}

void loop() {

 Serial.println("----- START TEST ----");
 test();
 Serial.println("----- END TEST ----");
 Serial.println("");
 delay(1000);

}

void test() {

 byte val1 = read_byte_data_at(VL53L0X_REG_IDENTIFICATION_REVISION_ID);
 Serial.print("Revision ID: "); Serial.println(val1);
 val1 = read_byte_data_at(VL53L0X_REG_IDENTIFICATION_MODEL_ID);
 Serial.print("Device ID: "); Serial.println(val1);
 val1 = read_byte_data_at(VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD);
 Serial.print("PRE_RANGE_CONFIG_VCSEL_PERIOD="); Serial.println(val1); 
 Serial.print(" decode: "); Serial.println(VL53L0X_decode_vcsel_period(val1));
 val1 = read_byte_data_at(VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD);
 Serial.print("FINAL_RANGE_CONFIG_VCSEL_PERIOD="); Serial.println(val1);
 Serial.print(" decode: "); Serial.println(VL53L0X_decode_vcsel_period(val1));
 write_byte_data_at(VL53L0X_REG_SYSRANGE_START, 0x01);
 byte val = 0;
 int cnt = 0;
 while (cnt < 100) { // 1 second waiting time max
   delay(10);
   val = read_byte_data_at(VL53L0X_REG_RESULT_RANGE_STATUS);
   if (val & 0x01) break;
   cnt++;
 }
 if (val & 0x01) Serial.println("ready"); else Serial.println("not ready");
 read_block_data_at(0x14, 12);
 uint16_t acnt = makeuint16(gbuf[7], gbuf[6]);
 uint16_t scnt = makeuint16(gbuf[9], gbuf[8]);
 uint16_t dist = makeuint16(gbuf[11], gbuf[10]);
 byte DeviceRangeStatusInternal = ((gbuf[0] & 0x78) >> 3);
 Serial.print("ambient count: "); Serial.println(acnt);
 Serial.print("signal count: ");  Serial.println(scnt);
 Serial.print("distance ");       Serial.println(dist);
 Serial.print("status: ");        Serial.println(DeviceRangeStatusInternal);

}

uint16_t bswap(byte b[]) {

 // Big Endian unsigned short to little endian unsigned short
 uint16_t val = ((b[0] << 8) & b[1]);
 return val;

}

uint16_t makeuint16(int lsb, int msb) {

   return ((msb & 0xFF) << 8) | (lsb & 0xFF);

}

void write_byte_data(byte data) {

 Wire.beginTransmission(address);
 Wire.write(data);
 Wire.endTransmission();

}

void write_byte_data_at(byte reg, byte data) {

 // write data word at address and register
 Wire.beginTransmission(address);
 Wire.write(reg);
 Wire.write(data);
 Wire.endTransmission();

}

void write_word_data_at(byte reg, uint16_t data) {

 // write data word at address and register
 byte b0 = (data &0xFF);
 byte b1 = ((data >> 8) && 0xFF);
   
 Wire.beginTransmission(address);
 Wire.write(reg);
 Wire.write(b0);
 Wire.write(b1);
 Wire.endTransmission();

}

byte read_byte_data() {

 Wire.requestFrom(address, 1);
 while (Wire.available() < 1) delay(1);
 byte b = Wire.read();
 return b;

}

byte read_byte_data_at(byte reg) {

 //write_byte_data((byte)0x00);
 write_byte_data(reg);
 Wire.requestFrom(address, 1);
 while (Wire.available() < 1) delay(1);
 byte b = Wire.read();
 return b;

}

uint16_t read_word_data_at(byte reg) {

 write_byte_data(reg);
 Wire.requestFrom(address, 2);
 while (Wire.available() < 2) delay(1);
 gbuf[0] = Wire.read();
 gbuf[1] = Wire.read();
 return bswap(gbuf); 

}

void read_block_data_at(byte reg, int sz) {

 int i = 0;
 write_byte_data(reg);
 Wire.requestFrom(address, sz);
 for (i=0; i<sz; i++) {
   while (Wire.available() < 1) delay(1);
   gbuf[i] = Wire.read();
 }

}


uint16_t VL53L0X_decode_vcsel_period(short vcsel_period_reg) {

 // Converts the encoded VCSEL period register value into the real
 // period in PLL clocks
 uint16_t vcsel_period_pclks = (vcsel_period_reg + 1) << 1;
 return vcsel_period_pclks;

}

</per> GY-530 6.jpg