B4R Question Transform arduino code into b4r code

IVR

Member
Licensed User
Hi !, I would like to know if anyone can help me to convert the Arduino code VL530L0X posted to b4r.
Thank You
B4X:
#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;
}
 

Peter Simpson

Expert
Licensed User
If you do not want to use Inline C, then I suggest that you convert one function (Sub) at a time then try to do some sort of test to make sure the Sub has no errors, don't get your types mixed up.

The B4R rWire library does not use the following functions.
  • Wire.beginTransmission
  • Wire.endTransmission
What's your VB6 or VB.Net development skills like?

I don't own a VL53L0X Time of Flight laser ranging sensor, at £8 I can't personally see the use for one thus I don't have one.

If you create a post asking for somebody to convert the Adafruit_VL53L0X.h library then that will eliminate having to use Inline C.

5 minutes searching on the internet:

I've just had a look on the internet and I found the original source code and library by Adafruit Industries. I suggest that if you can't convert the code in your original and nobody wraps the library for you, then you should use the following Arduino IDE source code with B4R Inline C. Inlice C is simple enough to use especially with the code below, please look at @Erel excellent tutorial on using Inline C in B4R.
B4X:
#include "Adafruit_VL53L0X.h"

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

void setup() {
  Serial.begin(115200);

  // wait until serial port opens for native USB devices
  while (! Serial) {
    delay(1);
  }

  Serial.println("Adafruit VL53L0X test");
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }
  // power
  Serial.println(F("VL53L0X API Simple Ranging example\n\n"));
}


void loop() {
  VL53L0X_RangingMeasurementData_t measure;

  Serial.print("Reading a measurement... ");
  lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!

  if (measure.RangeStatus != 4) {  // phase failures have incorrect data
    Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
  } else {
    Serial.println(" out of range ");
  }

  delay(100);
}

Enjoy...
 
Last edited:
Upvote 0

IVR

Member
Licensed User
Thanks for the polite answer, I know both VB6 and VB.Net.
My request is that I should use I2C which in B4R is not possible.
The VL53L0X sensor uses as Arduino's I2C (SDA / SCL) transmission.
Since I only have to read the sensor distance, I had asked if someone had used it.
 
Upvote 0

kolbe

Active Member
Licensed User
Hi !, I would like to know if anyone can help me to convert the Arduino code VL530L0X posted to b4r.
Thank You

Where did you find this? Did you write it? Do you have a register map of this device or did you piece this together from the Pololu library?

I would appreciate it if you shared any other info you have on this device!! Would love to know more about setting the range and precision.

Code below is tested and works. Distance is correct.

What is ambient count, signal count, device_range_status_internal?

B4X:
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 300
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public Serial1 As Serial
    Private Master As WireMaster
    Private timer1 As Timer
   
    Private const VL53L0X_REG_IDENTIFICATION_MODEL_ID=0xc0 As Byte
    Private const VL53L0X_REG_IDENTIFICATION_REVISION_ID=0xc2 As Byte
    Private const VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD=0x50 As Byte
    Private const VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD=0x70 As Byte
    Private const VL53L0X_REG_SYSRANGE_START=0x00 As Byte
'    Private const VL53L0X_REG_RESULT_INTERRUPT_STATUS=0x13 As Byte
    Private const VL53L0X_REG_RESULT_RANGE_STATUS=0x14 As Byte
    Private const VL53L0X_address=0x29 As Byte
   
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
   
    timer1.Initialize("Timer1_Tick",1000)
    Master.Initialize
    Log("I2C Init")
   
    Get_Info
    timer1.Enabled=True
   
End Sub

Private Sub Timer1_Tick
    Get_Range
End Sub

'print out chip info
Private Sub Get_Info
   
    Private readbyte(1) As Byte
    Private writebyte(1) As Byte
   
    writebyte(0)=VL53L0X_REG_IDENTIFICATION_MODEL_ID
    Master.WriteTo2(VL53L0X_address,True,writebyte)
    readbyte = Master.RequestFrom(VL53L0X_address,1)
    Log("Revision ID: ",readbyte(0))
   
    writebyte(0)=VL53L0X_REG_IDENTIFICATION_REVISION_ID
    Master.WriteTo2(VL53L0X_address,True,writebyte)
    readbyte = Master.RequestFrom(VL53L0X_address,1)
    Log("Device ID: ",readbyte(0))
   
    writebyte(0)=VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD
    Master.WriteTo2(VL53L0X_address,True,writebyte)
    readbyte = Master.RequestFrom(VL53L0X_address,1)
    Log("Prerange: ",readbyte(0))
    Log("Decode: ",Bit.ShiftRight(readbyte(0)+1,1))
   
    writebyte(0)=VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD
    Master.WriteTo2(VL53L0X_address,True,writebyte)
    readbyte = Master.RequestFrom(VL53L0X_address,1)
    Log("Prerange: ",readbyte(0))
    Log("Decode: ",Bit.ShiftRight(readbyte(0)+1,1))
    Log("--")
   
End Sub

'call to get range reading in mm
private Sub Get_Range
    Send_Start 'must call before each reading
   
    Private readbyte(1) As Byte
    Private writebyte(1) As Byte
    writebyte(0)=VL53L0X_REG_RESULT_RANGE_STATUS
    Private ready As Boolean = False
    Private count As Int = 0
   
    'wait for data to be ready
    Do Until ready
        Master.WriteTo2(VL53L0X_address,True,writebyte)
       
        readbyte = Master.RequestFrom(VL53L0X_address,1)
       
        If readbyte.Length=1 Then
            If Bit.Get(readbyte(0),0)=1 Then ready=True
        Else
            Log("length error ",readbyte.Length)
        End If
       
        count=count+1
        If count > 100 Then Exit
'        Log(count," ",Bit.ToBinaryString(readbyte(0)))
    Loop
   
    'now retrieve data
    writebyte(0)=VL53L0X_REG_RESULT_RANGE_STATUS
    Master.WriteTo2(VL53L0X_address,True,writebyte)
   
    readbyte = Master.RequestFrom(VL53L0X_address,12)
   
    If readbyte.Length=12 Then
        Private acnt, scnt, dist, dev_range_status_int As UInt
        acnt=Bit.ShiftLeft(readbyte(6),8)+ readbyte(7)
        scnt=Bit.ShiftLeft(readbyte(8),8)+ readbyte(9)
        dist=Bit.ShiftLeft(readbyte(10),8)+ readbyte(11)
        dev_range_status_int=Bit.ShiftRight(Bit.And(readbyte(0),0x78),3)
        Log(acnt," ",scnt," ",dist," ",dev_range_status_int)
    End If
End Sub

Private Sub Send_Start
    Private writebyte(2) As Byte
    writebyte(0)=VL53L0X_REG_SYSRANGE_START
    writebyte(1)=0x01
    Master.WriteTo2(VL53L0X_address,True,writebyte)
End Sub
 
Upvote 0

Peter Simpson

Expert
Licensed User
I would appreciate it if you shared any other info you have on this device!! Would love to know more about setting the range and precision.

Code below is tested and works. Distance is correct.

What is ambient count, signal count, device_range_status_internal?

Nice coding BTW, you have more time to kill than I do :p

I've ordered one of these devices today for only £6. All your questions can be answered my doing a simple Google search. Adafruit sells kit, but in any case there's lots in code and information about it on the net.

From what I've read the range is quite decent and apparently it's extremely accurate too, depending on the quality of the device that you purchase...
 
Upvote 0

kolbe

Active Member
Licensed User
Nice coding BTW, you have more time to kill than I do :p

I've ordered one of these devices today for only £6. All your questions can be answered my doing a simple Google search. Adafruit sells kit, but in any case there's lots in code and information about it on the net.

From what I've read the range is quite decent and apparently it's extremely accurate too, depending on the quality of the device that you purchase...

Available? Yes and No. Unlike 99% of the stuff out there, no register map was published by ST. :( All their docs say is "use our API" because the device is too complicated for mere mortals. So people have slowly been reverse engineering how to access the registers. This was the first code I saw that gave you a quick idea on how to get a distance measurement. For the code I posted I was hoping for a little quid pro quo and more light on low level functions, setting the precision and range etc. I now see where IVR copied it from so I don't suspect he knows much about how it works.

What I really should do is figure out how to wrap the arduino libraries out there... but I prefer low level hacking. :)
 
Upvote 0

IVR

Member
Licensed User
Hi, I wanted to thank you for the code you have developed and I still have to try it on the hardware. The product I use is at this address:https://www.amazon.it/Cloud-Sensore-Vl53L0X-Distanza-isurazione/dp/B01N476D4X For the moment I am only interested in the distance.
cleardot.gif
 
Upvote 0

IVR

Member
Licensed User
Hi, You are a great one, the code works perfectly.
I was going to develop the library, but at this point I do not need it.
 
Upvote 0
Top