0

VL53L0X fails PerformRefCalibration
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Re: VL53L0X fails PerformRefCalibration

by adafruit2 on Mon Dec 05, 2016 9:32 pm

huh! nice find! we couldn't download the file but we updated the library
https://github.com/adafruit/Adafruit_VL ... f7f9da22db

can you try the latest library for us? we couldnt get our sensor to fail the same way so not 100% sure its fixed unless you try too!
https://github.com/adafruit/Adafruit_VL ... master.zip
is the latest - just delete the old version you've got and re-try the example :)

adafruit2
Site Admin
 
Posts: 18231
Joined: Fri Mar 11, 2005 7:36 pm

Re: VL53L0X fails PerformRefCalibration

by jerryn on Mon Dec 05, 2016 9:41 pm

sigh - Apparently, that was not the whole story....
The modified Adafruit code does work, but only after running the working Pololu code first!!!
Clearly something is still not right.
If I reset the board, it goes back to failing and has the be power cycled in order to get the Pololu code working again.

Still digging...

jerryn
 
Posts: 886
Joined: Sat Sep 14, 2013 9:05 am

Re: VL53L0X fails PerformRefCalibration

by jerryn on Mon Dec 05, 2016 9:56 pm

I tried the new library and It still does not work for me. I can get my version to work if I power cycle. load the Pololu code then load the new version ....
Sorry for the false hope.

Does this library work for you?

jerryn
 
Posts: 886
Joined: Sat Sep 14, 2013 9:05 am

Re: VL53L0X fails PerformRefCalibration

by jerryn on Mon Dec 05, 2016 10:36 pm

Another place there is a signifiant difference between the Adafruit code and the Pololu code is in the execution of the DataInit step. I have not been able to wade through it all yet, but there may be some problem since according the the API, DataInit can only be run one time after a RESET.
There is some reference to setting the I2C to 1v8 or 2v8 mode? How should this be set and is it being set correctly? I may be misreading the comments, but there may be a difference here.

No more time to dig tonight. I'll try to get back to it tomorrow,

jerryn
 
Posts: 886
Joined: Sat Sep 14, 2013 9:05 am

Re: VL53L0X fails PerformRefCalibration

by jerryn on Wed Dec 07, 2016 8:40 am

The more I dig into this, the more confused I get ;-)
Would you please confirm that the current Adafruit_VL53L0X library does in fact work for you?

What do you have it connected to? I have tried both an Arduino Uno and and ATMEGA32U4 with similar results so I don't think it has anything to do with the platform.

I am expecting a second board in a day or 2 and will see if it behaves any differently.

There are vast differences in how the Pololu code initializes the board from how the AdaFruit Library does it so I am focusing on that. I just find it very odd that it works "sometimes" using the AdaFruit library but only after a clean start with the Pololu code first.

I am concerned about how the AdaFruit Ranging Test re-executes many of the Initialization steps every time it loops rather than just once before starting but so far I am not able to get my board to pass the Adafruit Library Initialization reliably.

At least I'm having fun .... ;-)

jerryn
 
Posts: 886
Joined: Sat Sep 14, 2013 9:05 am

Re: VL53L0X fails PerformRefCalibration

by adafruit2 on Wed Dec 07, 2016 2:01 pm

we use a arduino 328 - you should compare the code with the official API if you're curious
http://www.st.com/en/imaging-and-photon ... 53l0x.html
has the official 'embedded software'

adafruit2
Site Admin
 
Posts: 18231
Joined: Fri Mar 11, 2005 7:36 pm

Re: VL53L0X fails PerformRefCalibration

by jerryn on Wed Dec 07, 2016 8:36 pm

Major progress:
I downloaded https://github.com/cassou/VL53L0X_rasp
and built it on my Raspberry Pi (Model 3) .
It works " out of the box" with the VL53L0X board that has been failing with he Adafruit Arduino Library.
At first glance, the operation "appears" similar to what is in the Adafruit Library but I have not had time to delve into details.

Note; this uses the ST API distribution as its base.

I am thrilled because this means I can work directly from the Pi and bypass the Auduino IDE (not my favorite environment ;-)

I will continue to try to understand what is going one with the Adafruit Arduino Library and share any findings.

The game is afoot ... ;-)

jerryn
 
Posts: 886
Joined: Sat Sep 14, 2013 9:05 am

Re: VL53L0X fails PerformRefCalibration

by jerryn on Fri Dec 09, 2016 8:17 am

I hope someone can help solve a mystery.
In the ST API code there is a configuration parameter that is defined (or not) at compile time. USE_I2C_2V8. It is used in DataInit to set a bit on one of the control registers.
The AdaFruit Library includes a statement #define USE_I2C_2V8 so this should be compiled in and executed. The Pololu code appears to all set this but via some other logic. C Raspberry Pi C example using the standard ST API core does not define this so it would appear that it is not being set for that example.

Here is a code snippet where the configuration parameter is used.
Code: Select all | TOGGLE FULL SIZE
VL53L0X_Error VL53L0X_DataInit(VL53L0X_DEV Dev)
{
   VL53L0X_Error Status = VL53L0X_ERROR_NONE;
   VL53L0X_DeviceParameters_t CurrentParameters;
   int i;
   uint8_t StopVariable;

   LOG_FUNCTION_START("");

   /* by default the I2C is running at 1V8 if you want to change it you
    * need to include this define at compilation level. */
#ifdef USE_I2C_2V8
   Status = VL53L0X_UpdateByte(Dev,
      VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV,
      0xFE,
      0x01);
#endif

   /* Set I2C standard mode */
   if (Status == VL53L0X_ERROR_NONE)
      Status = VL53L0X_WrByte(Dev, 0x88, 0x00);



Can you shed any light on what this setting actually does? From the documentation, It looks like it determines if the I2C core on the VL53L0X runs at 1.8 or 2.8 V.
I assume the AdaFruit Board should be set to run at 2.8V, correct? Should it work if this bit is not set? It appears to. Is this a concern?

My experience so far:
Pololu examples work fine under Arduino IDE
AdaFruit Libray does not work under Arduino IDE - inconsistent behavior depending on what was executed/power cycled immediately prior to execution.
Raspberry Pi C example works fine ( but I don't understand the setting of the USE_I2C_2V8)

The flow of the Raspberry Pi C example is nearly identical to the AdaFruit Aduino IDE example. Clearly they have a common history including a few minor typos. I'll clean those up when I have an update for you ;-) I'm still trying to find the cause of the flaky behavior of the AdaFruit Library. This confusion with eh I2C_2V8 setting is something I would like to clarify.

Any insights would be appreciated.

An aside: early on, I found that the AdaFruit example had two of the initialization steps out of order and you updated the Library. at first I thought it helped, but not really. I see that in the Raspberry Pi C example, the same (what I claim) erroneous sequence is executed. I have swapped it and it does not actually appear to make any difference at all! According to the ST document one should execute the Spad calibration before the Ref Calibration so I think my suggested correction is valid, but probably not critical.


Thanks

jerryn
 
Posts: 886
Joined: Sat Sep 14, 2013 9:05 am

Re: VL53L0X fails PerformRefCalibration

by adafruit2 on Fri Dec 09, 2016 1:31 pm

yah it should be set to 2.8V, you do that at boot to tell the chip which voltage to expect for power/logic

adafruit2
Site Admin
 
Posts: 18231
Joined: Fri Mar 11, 2005 7:36 pm

Re: VL53L0X fails PerformRefCalibration

by jerryn on Fri Dec 09, 2016 1:36 pm

What happens if it is set wrong? ... Hopefully nothing too bad...

jerryn
 
Posts: 886
Joined: Sat Sep 14, 2013 9:05 am

Re: VL53L0X fails PerformRefCalibration

by adafruit2 on Fri Dec 09, 2016 1:51 pm

no idea what happens, that's all internal to the sensor :)

adafruit2
Site Admin
 
Posts: 18231
Joined: Fri Mar 11, 2005 7:36 pm

Re: VL53L0X fails PerformRefCalibration

by jerryn on Fri Dec 09, 2016 11:14 pm

Well, it looks like the problems I was having with the AdaFruit Library were caused by the use of memcpy in the src/platform/src/vl53l0x_i2c_comms.cpp file. There were some clear errors with the passing of arguments that were pointed out in the thread regarding problems with compiling for the M0.
I adapted the code from cassou's Raspberry Pi example: https://github.com/cassou/VL53L0X_rasp

I had tried correcting the data pointers to memcpy, but that was not sufficient. I'll admit I have not unravelled all the mysteries of memcpy and endian-ness but this seem sot work for me!

Here is the modified file:
Code: Select all | TOGGLE FULL SIZE
#include "vl53l0x_i2c_platform.h"
#include "vl53l0x_def.h"

//#define I2C_DEBUG

int VL53L0X_i2c_init(void) {
  Wire.begin();
  return VL53L0X_ERROR_NONE;
}

int VL53L0X_write_multi(uint8_t deviceAddress, uint8_t index, uint8_t *pdata, uint32_t count) {
  Wire.beginTransmission(deviceAddress);
  Wire.write(index);
#ifdef I2C_DEBUG
  Serial.print("\tWriting "); Serial.print(count); Serial.print(" to addr 0x"); Serial.print(index, HEX); Serial.print(": ");
#endif
  while(count--) {
    Wire.write((uint8_t)pdata[0]);
#ifdef I2C_DEBUG
    Serial.print("0x"); Serial.print(pdata[0], HEX); Serial.print(", ");
#endif
    pdata++;
  }
#ifdef I2C_DEBUG
  Serial.println();
#endif
  Wire.endTransmission();
  return VL53L0X_ERROR_NONE;
}

int VL53L0X_read_multi(uint8_t deviceAddress, uint8_t index, uint8_t *pdata, uint32_t count) {
  Wire.beginTransmission(deviceAddress);
  Wire.write(index);
  Wire.endTransmission();
  Wire.requestFrom(deviceAddress, (byte)count);
#ifdef I2C_DEBUG
  Serial.print("\tReading "); Serial.print(count); Serial.print(" from addr 0x"); Serial.print(index, HEX); Serial.print(": ");
#endif

  while (count--) {
    pdata[0] = Wire.read();
#ifdef I2C_DEBUG
    Serial.print("0x"); Serial.print(pdata[0], HEX); Serial.print(", ");
#endif
    pdata++;
  }
#ifdef I2C_DEBUG
  Serial.println();
#endif
  return VL53L0X_ERROR_NONE;
}

int VL53L0X_write_byte(uint8_t deviceAddress, uint8_t index, uint8_t data) {
  return VL53L0X_write_multi(deviceAddress, index, &data, 1);
}

int VL53L0X_write_word(uint8_t deviceAddress, uint8_t index, uint16_t data) {
  uint8_t buf[4];
  buf[1] = data>>0&0xFF;
  buf[0] = data>>8&0xFF;
  return VL53L0X_write_multi(deviceAddress, index, buf, 2);
}

int VL53L0X_write_dword(uint8_t deviceAddress, uint8_t index, uint32_t data) {
  uint8_t buf[4];
  buf[3] = data>>0&0xFF;
  buf[2] = data>>8&0xFF;
  buf[1] = data>>16&0xFF;
  buf[0] = data>>24&0xFF;
  return VL53L0X_write_multi(deviceAddress, index, buf, 4);
}

int VL53L0X_read_byte(uint8_t deviceAddress, uint8_t index, uint8_t *data) {
  return VL53L0X_read_multi(deviceAddress, index, data, 1);
}

int VL53L0X_read_word(uint8_t deviceAddress, uint8_t index, uint16_t *data) {
  uint8_t buf[2];
  int r = VL53L0X_read_multi(deviceAddress, index, buf, 2);
  uint16_t tmp = 0;
  tmp |= buf[1]<<0;
  tmp |= buf[0]<<8;
  *data = tmp;
  return r;
}

int VL53L0X_read_dword(uint8_t deviceAddress, uint8_t index, uint32_t *data) {
  uint8_t buf[4];
  int r = VL53L0X_read_multi(deviceAddress, index, buf, 4);
  uint32_t tmp = 0;
  tmp |= buf[3]<<0;
  tmp |= buf[2]<<8;
  tmp |= buf[1]<<16;
  tmp |= buf[0]<<24;
  *data = tmp;
  return r;
}


With this file, my VL53L0X board works with the Arduino UNO. Yay!

I then tried compiling for the Feather M0 (Ada logger) and had on more compiler complaint regarding the initialization of the boolean argument to Rangingtest. It was initialized both in the .h file and in the .cpp file. I removed the initialization in the .cpp file and it compiles and works on my Feather M0 as well!!

Here is the modified src/Adafruit_VL53l0X.cpp file
Code: Select all | TOGGLE FULL SIZE
#include "Adafruit_VL53L0X.h"

#define VERSION_REQUIRED_MAJOR 1
#define VERSION_REQUIRED_MINOR 0
#define VERSION_REQUIRED_BUILD 1
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)


boolean Adafruit_VL53L0X::begin(void) {
  int32_t status_int;
  int32_t init_done = 0;

  // Initialize Comms
  pMyDevice->I2cDevAddr      = 0x29;  // 7 bit addr
  pMyDevice->comms_type      =  1;
  pMyDevice->comms_speed_khz =  400;

 
  Wire.begin();  // VL53L0X_i2c_init();

  // unclear if this is even needed:
  if( VL53L0X_IMPLEMENTATION_VER_MAJOR != VERSION_REQUIRED_MAJOR ||
      VL53L0X_IMPLEMENTATION_VER_MINOR != VERSION_REQUIRED_MINOR ||
      VL53L0X_IMPLEMENTATION_VER_SUB != VERSION_REQUIRED_BUILD )  {

    Serial.println(F("Found " STR(VL53L0X_IMPLEMENTATION_VER_MAJOR) "." STR(VL53L0X_IMPLEMENTATION_VER_MINOR) "."  STR(VL53L0X_IMPLEMENTATION_VER_SUB) " rev " STR(VL53L0X_IMPLEMENTATION_VER_REVISION)));
    Serial.println(F("Requires " STR(VERSION_REQUIRED_MAJOR) "." STR(VERSION_REQUIRED_MINOR) "." STR(VERSION_REQUIRED_BUILD)));
    return false;
  }

  Status = VL53L0X_DataInit(&MyDevice); // Data initialization

  Status = VL53L0X_GetDeviceInfo(&MyDevice, &DeviceInfo);
  if (Status != VL53L0X_ERROR_NONE)
    return false;

  if(Status == VL53L0X_ERROR_NONE)  {
  /*
     Serial.println(F("VL53L0X_GetDeviceInfo:"));
     Serial.print(F("Device Name : ")); Serial.println(DeviceInfo.Name);
     Serial.print(F("Device Type : ")); Serial.println(DeviceInfo.Type);
     Serial.print(F("Device ID : ")); Serial.println(DeviceInfo.ProductId);
     Serial.print(F("ProductRevisionMajor : ")); Serial.println(DeviceInfo.ProductRevisionMajor);
     Serial.print(F("ProductRevisionMinor : ")); Serial.println(DeviceInfo.ProductRevisionMinor);
  */
     if ((DeviceInfo.ProductRevisionMinor != 1) && (DeviceInfo.ProductRevisionMinor != 1)) {
       /*
       Serial.print(F("Error expected cut 1.1 but found cut "));
       Serial.print(DeviceInfo.ProductRevisionMajor);
       Serial.print('.');
       Serial.println(DeviceInfo.ProductRevisionMinor);
       */
       Status = VL53L0X_ERROR_NOT_SUPPORTED;
       return false;     
     }
  }
  return true;
}


VL53L0X_Error Adafruit_VL53L0X::rangingTest(VL53L0X_RangingMeasurementData_t *RangingMeasurementData, boolean debug)
{
    VL53L0X_Error Status = VL53L0X_ERROR_NONE;
    int i;
    FixPoint1616_t LimitCheckCurrent;
    uint32_t refSpadCount;
    uint8_t isApertureSpads;
    uint8_t VhvSettings;
    uint8_t PhaseCal;

    if(Status == VL53L0X_ERROR_NONE)
    {
      if (debug)
   Serial.println(F("Call of VL53L0X_StaticInit"));
      Status = VL53L0X_StaticInit(pMyDevice); // Device Initialization
    }
   
    if(Status == VL53L0X_ERROR_NONE)
    {
      if (debug)
        Serial.println(F("Call of VL53L0X_PerformRefSpadManagement"));
      Status = VL53L0X_PerformRefSpadManagement(pMyDevice,
            &refSpadCount, &isApertureSpads); // Device Initialization
      if (debug) {
   Serial.print(F("refSpadCount = "));
        Serial.print(refSpadCount);
        Serial.print(F(", isApertureSpads = "));
        Serial.println(isApertureSpads);
      }
    }

    if(Status == VL53L0X_ERROR_NONE)
    {
      if (debug)
        Serial.println(F("Call of VL53L0X_PerformRefCalibration"));
      Status = VL53L0X_PerformRefCalibration(pMyDevice,
      &VhvSettings, &PhaseCal); // Device Initialization
    }

    if(Status == VL53L0X_ERROR_NONE)
    {
        // no need to do this when we use VL53L0X_PerformSingleRangingMeasurement
      if (debug)
        Serial.println(F("Call of VL53L0X_SetDeviceMode"));
      Status = VL53L0X_SetDeviceMode(pMyDevice, VL53L0X_DEVICEMODE_SINGLE_RANGING); // Setup in single ranging mode
    }

    // Enable/Disable Sigma and Signal check
    if (Status == VL53L0X_ERROR_NONE) {
        Status = VL53L0X_SetLimitCheckEnable(pMyDevice,
            VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 1);
    }
    if (Status == VL53L0X_ERROR_NONE) {
        Status = VL53L0X_SetLimitCheckEnable(pMyDevice,
            VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 1);
    }

    if (Status == VL53L0X_ERROR_NONE) {
        Status = VL53L0X_SetLimitCheckEnable(pMyDevice,
            VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 1);
    }

    if (Status == VL53L0X_ERROR_NONE) {
        Status = VL53L0X_SetLimitCheckValue(pMyDevice,
            VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
            (FixPoint1616_t)(1.5*0.023*65536));
    }


    /*
     *  Step  4 : Test ranging mode
     */

    if(Status == VL53L0X_ERROR_NONE)
    {
      if (debug)
   Serial.println(F("Call of VL53L0X_PerformSingleRangingMeasurement"));
      Status = VL53L0X_PerformSingleRangingMeasurement(pMyDevice,
                         RangingMeasurementData);
     
      if (debug)
   print_range_status(RangingMeasurementData);
     
      VL53L0X_GetLimitCheckCurrent(pMyDevice,
               VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, &LimitCheckCurrent);
     
      if (debug) {
   Serial.print(F("RANGE IGNORE THRESHOLD: "));
   Serial.println((float)LimitCheckCurrent/65536.0);
   
   Serial.print(F("Measured distance: "));
   Serial.println(RangingMeasurementData->RangeMilliMeter);
      }
    }
    return Status;
}




void Adafruit_VL53L0X::print_range_status(VL53L0X_RangingMeasurementData_t* pRangingMeasurementData){
    char buf[VL53L0X_MAX_STRING_LENGTH];
    uint8_t RangeStatus;

    /*
     * New Range Status: data is valid when pRangingMeasurementData->RangeStatus = 0
     */

    RangeStatus = pRangingMeasurementData->RangeStatus;

    VL53L0X_GetRangeStatusString(RangeStatus, buf);
    Serial.print(F("Range Status: "));
    Serial.print(RangeStatus);
    Serial.print(" : ");
    Serial.println(buf);

}


By the way, I also fixed the Raspberry Pi version to set USE_I2C_2V8 and all seems to be well there.

Now I can get actually get down to using this thing!!

jerryn
 
Posts: 886
Joined: Sat Sep 14, 2013 9:05 am

Re: VL53L0X fails PerformRefCalibration

by h8me on Sat Dec 10, 2016 12:00 pm

jerryn wrote: I'll admit I have not unravelled all the mysteries of memcpy and endian-ness but this seem sot work for me!


Just FYI most microcontrollers/CPU's store integer data in either Big endian or Little endian. Say you have a 2 byte integer (made up of a high order byte and low order byte). If it is big endian, it will store the high order byte in the first (lowest) memory address and the low order byte in the next byte. Little endian is the opposite order (low order byte comes first and then the high order byte).

memcpy doesn't know (or care) anything about endian-ness because it takes a void pointer and just copies the bytes over in whatever order the values are in memory. To memcpy everything just looks like an array of bytes..

Since the library should send over the bytes in a particular order, one should use bit shifting and bitwise operators to extract each byte. Bitwise operators on integers are agnostic about the endianess of the processor/microcontroller. It's the 'safe' way to extract the bytes and ordering them for transmitting over i2c.

h8me
 
Posts: 20
Joined: Fri Oct 28, 2011 12:00 pm

Re: VL53L0X fails PerformRefCalibration

by jerryn on Tue Dec 13, 2016 11:11 am

Adafruit folks:
Have you had a chance to look over the submitted changes? I was wondering if you have any concerns with them or recommend additional changes? Will you be incorporating them into the released library?

Have you found that the current library actually works for you? Just curious.

Thanks.

jerryn
 
Posts: 886
Joined: Sat Sep 14, 2013 9:05 am

Re: VL53L0X fails PerformRefCalibration

by adafruit2 on Tue Dec 13, 2016 1:49 pm

we have not had a chance yet!

adafruit2
Site Admin
 
Posts: 18231
Joined: Fri Mar 11, 2005 7:36 pm

Please be positive and constructive with your questions and comments.