ESP32 driver GY-530 (VL53L0X) full code

GY-530 is a tiny ToF ranging module based on 940nm infrared. It has a built-in VL53L10 chip and has an absolute measurement range of 2 meters. There are relatively few codes driven by arduino on the Internet, so write a blog to record it.

Based on Arduino IDE, all MCUs that support arduino compilation can use this code

Driving a single VL53L0

The SDA and SCL of the module should be connected to the I2C pin of the MCU.

#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

//VL53L0的默认I2C地址
#define address 0x29

byte gbuf[16];

void setup() {
    
    
  // put your setup code here, to run once:
  Wire.begin(25,26);        // 引脚25是SDA,26是SCL,可以自己设置其他引脚
  Serial.begin(115200);  // start serial for output
  Serial.println("VLX53LOX test started.");
}

void loop() {
    
    
//每50ms测一次距离值
  test();
  delay(50);
}

void test() {
    
    
  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++;
  }
  read_block_data_at(0x14, 12);
  uint16_t dist = makeuint16(gbuf[11], gbuf[10]);
  Serial.print("distance ");
  Serial.println(dist);
}

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;
}

 

Drive two VL53L0

If you buy the same two modules, their I2C address is 0x29 by default, and they cannot communicate on the same I2C bus at this time. One way is to modify the I2C address by software, but every time the breakpoint is restarted, the address of the module becomes 0x29 again, and each time you change one of them, you must disconnect one of them before you can accurately modify the address of the other, otherwise the two addresses will be changed together. So the most convenient way is to use two I2C buses. Generally, MCUs will have two or more I2C resources.

//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];
byte gbuf1[16];

void setup() {
    
    

  Wire.begin(25,26);        // join i2c bus (address optional for master)
  Wire1.begin(21,22);
  Serial.begin(115200);  // start serial for output
  Serial.println("VLX53LOX test started.");
}

void loop() {
    
    

  test();
  delay(100);
  
}

void test() {
    
    

  write_byte_data_at(VL53L0X_REG_SYSRANGE_START, 0x01);
  write_byte_data_at1(VL53L0X_REG_SYSRANGE_START, 0x01);

  byte val = 0;
  byte val1 = 0;
  
  int cnt = 0;
  int cnt1 = 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++;
  }

   while (cnt1 < 100) {
    
     // 1 second waiting time max
    delay(10);
    val1 = read_byte_data_at1(VL53L0X_REG_RESULT_RANGE_STATUS);
    if (val1 & 0x01) break;
    cnt1++;
  }

  read_block_data_at(0x14, 12);
  uint16_t dist1 = makeuint16(gbuf[11], gbuf[10]);
  read_block_data_at1(0x14, 12);
  uint16_t dist2 = makeuint16(gbuf1[11], gbuf1[10]);


    Serial.print("distance1:");
    Serial.print(dist1);
    Serial.print(" distance2:");   
    Serial.println(dist2);

}

uint16_t bswap(byte b[]) {
    
    
  uint16_t val = ((b[0] << 8) & b[1]);
  return val;
}
uint16_t bswap1(byte b[]) {
    
    
  uint16_t val1 = ((b[0] << 8) & b[1]);
  return val1;
}

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_data1(byte data) {
    
    
  Wire1.beginTransmission(address);
  Wire1.write(data);
  Wire1.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_byte_data_at1(byte reg, byte data) {
    
    
  // write data word at address and register
  Wire1.beginTransmission(address);
  Wire1.write(reg);
  Wire1.write(data);
  Wire1.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();
}
void write_word_data_at1(byte reg, uint16_t data) {
    
    
  // write data word at address and register
  byte b0 = (data &0xFF);
  byte b1 = ((data >> 8) && 0xFF);
    
  Wire1.beginTransmission(address);
  Wire1.write(reg);
  Wire1.write(b0);
  Wire1.write(b1);
  Wire1.endTransmission();
}

byte read_byte_data() {
    
    
  Wire.requestFrom(address, 1);
  while (Wire.available() < 1) delay(1);
  byte b = Wire.read();
  return b;
}
byte read_byte_data1() {
    
    
  Wire1.requestFrom(address, 1);
  while (Wire1.available() < 1) delay(1);
  byte b = Wire1.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;
}
byte read_byte_data_at1(byte reg) {
    
    
  //write_byte_data((byte)0x00);
  write_byte_data1(reg);
  Wire1.requestFrom(address, 1);
  while (Wire1.available() < 1) delay(1);
  byte b = Wire1.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); 
}
uint16_t read_word_data_at1(byte reg) {
    
    
  write_byte_data1(reg);
  Wire1.requestFrom(address, 2);
  while (Wire1.available() < 2) delay(1);
  gbuf1[0] = Wire1.read();
  gbuf1[1] = Wire1.read();
  return bswap1(gbuf1); 
}

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();
  }
}
void read_block_data_at1(byte reg, int sz) {
    
    
  int i = 0;
  write_byte_data1(reg);
  Wire1.requestFrom(address, sz);
  for (i=0; i<sz; i++) {
    
    
    while (Wire1.available() < 1) delay(1);
    gbuf1[i] = Wire1.read();
  }
}


uint16_t VL53L0X_decode_vcsel_period(short vcsel_period_reg) {
    
    
  uint16_t vcsel_period_pclks = (vcsel_period_reg + 1) << 1;
  return vcsel_period_pclks;
}

It is also possible to do it with a library Adafruit_VL53L0X.

Guess you like

Origin blog.csdn.net/weixin_45116099/article/details/130304887