ESP32驱动GY-530 (VL53L0X) 全代码
GY-530是一个微小的基于940nm红外进行ToF测距的模块,内置VL53L10芯片,测量绝对范围为2米,可用来用户检测、机器人避障、手势识别、激光辅助自动对焦等,工作电压2.6-3.5V。网上用arduino来驱动的代码比较少,所以写个博客记录一下。
基于Arduino IDE,所有支持arduino编译的MCU都可以用这个代码
目录
- 驱动单个VL53L0
- 驱动两个VL53L0
驱动单个VL53L0
模块的SDA、SCL对应接到MCU的I2C引脚上就好了。
#include #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 0x29byte 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 outputSerial.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 maxdelay(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 shortuint16_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 registerWire.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 registerbyte 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 clocksuint16_t vcsel_period_pclks = (vcsel_period_reg + 1) << 1;return vcsel_period_pclks;
}
驱动两个VL53L0
如果买到相同的两个模块,它们的I2C地址默认都是0x29,这时无法在同一条I2C总线上通信。有一个方法是软件修改I2C地址,但是每次断点重启,模块的地址又变为0x29,而且每次改都要先断开其中一个,才能准确修改另一个的地址,不然两个地址会一起被改。所以最方便的方法,就是用两条I2C总线,一般MCU都会有2个或以上的I2C资源。
//the original code by Ted Meyers
//posted here: https://groups.google.com/d/msg/diyrovers/lc7NUZYuJOg/ICPrYNJGBgAJ#include #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 0x29byte 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 outputSerial.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 maxdelay(10);val = read_byte_data_at(VL53L0X_REG_RESULT_RANGE_STATUS);if (val & 0x01) break;cnt++;}while (cnt1 < 100) { // 1 second waiting time maxdelay(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 registerWire.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 registerWire1.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 registerbyte 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 registerbyte 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;
}
也可以用一个库 Adafruit_VL53L0X 来做。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
