2020-01-08 10:23 PM
I use VL53L1X ultra lite driver.
For example:
The value written to ALGO__PART_TO_PART_RANGE_OFFSET_MM(0x001E) register is 0xFF24 when VL53L1X_SetOffset() is called with OffsetValue -55.
The value got from ALGO__PART_TO_PART_RANGE_OFFSET_MM(0x001E) register is 0x1F24 when VL53L1X_GetOffset is called and the returned offset value is 1993.
I meet this issue when offset value < 0.
2020-01-13 11:13 AM
VL53L1X_ERROR VL53L1X_SetOffset(VL53L1_Dev_t dev, int16_t OffsetValue)
{
VL53L1X_ERROR status = 0;
int16_t Temp;
Temp = (OffsetValue*4);
VL53L1_WrWord(&dev, ALGO__PART_TO_PART_RANGE_OFFSET_MM,
(uint16_t)Temp);
VL53L1_WrWord(&dev, MM_CONFIG__INNER_OFFSET_MM, 0x0);
VL53L1_WrWord(&dev, MM_CONFIG__OUTER_OFFSET_MM, 0x0);
return status;
}
VL53L1X_ERROR VL53L1X_GetOffset(VL53L1_Dev_t dev, int16_t *offset)
{
VL53L1X_ERROR status = 0;
uint16_t Temp;
status = VL53L1_RdWord(&dev,ALGO__PART_TO_PART_RANGE_OFFSET_MM, &Temp);
Temp = Temp<<3;
Temp = Temp >>5;
*offset = (int16_t)(Temp);
return status;
}
The register is 13 bits. And the value is stored in mm.XX where XX are the fractional parts of millimeters (mm).
So if the offset wants to be 12mm, 12 x 4 would be stored in the register. (Offset Value*4)
When the register is retrieved, we read the value, Shift up by 3 to eliminate any 'junk' bits, then right shift by 5 to get back to mm.
So what we have here is a sign issue.
I believe the correct code should be:
VL53L1X_ERROR VL53L1X_GetOffset(VL53L1_Dev_t dev, int16_t *offset)
{
VL53L1X_ERROR status = 0;
uint16_t Temp;
status = VL53L1_RdWord(&dev,ALGO__PART_TO_PART_RANGE_OFFSET_MM, &Temp);
Temp = Temp<<3;
Temp = Temp >>5;
if((Temp & 0x1000) !=0) Temp = Temp|0xF000);
*offset = (int16_t)(Temp);
return status;
}
Where we added line 9 - A mod to check the sign bit, and make a negative value before returning.
Please double check my code if you use it, there is no peer review.
2020-01-13 11:50 AM
Upon double checking the definition of a right shift is implementation dependent. Meaning some MCUs will sign extend and some will not.
Clearly yours does not do sign extension.
2020-01-13 06:33 PM
Follow the above modification, the returned offset value is still incorrect.
VL53L1X_ERROR VL53L1X_GetOffset(VL53L1_Dev_t dev, int16_t *offset)
{
VL53L1X_ERROR status = 0;
uint16_t Temp;
status = VL53L1_RdWord(&dev,ALGO__PART_TO_PART_RANGE_OFFSET_MM, &Temp); //Temp is 0x1F24 if offset is -55.
Temp = Temp<<3;
Temp = Temp>>5; // Temp is 0x07C9
if((Temp & 0x1000) !=0) Temp = Temp|0xF000;
*offset = (int16_t)(Temp); // Temp is 0x07C9
return status;
}
I modify VL53L1X_GetOffset as bellow. The returned offset value is the same as the one set in the VL53L1X_SetOffset function.
Is this correct ?
VL53L1X_ERROR VL53L1X_GetOffset(VL53L1_Dev_t dev, int16_t *offset)
{
VL53L1X_ERROR status = 0;
uint16_t Temp;
status = VL53L1_RdWord(&dev,ALGO__PART_TO_PART_RANGE_OFFSET_MM, &Temp);
Temp = Temp<<3;
Temp = Temp>>5;
if((Temp & 0x0400) !=0) Temp = Temp|0xF800;
*offset = (int16_t)(Temp);
return status;
}
2020-09-29 03:37 AM
Hello @RChen.1654 .
I had the same problem. After much debugging and much trial and error, I have come to the same conclusion as you:
if((Temp & 0x0400) !=0) Temp = Temp|0xF800;
For example:
VL53L1X_CalibrateOffset() calculates OFFSET = -265 = 0xFEF7 = 1111 1110 1111 0111 --> This is stored in sensor's internal memory.
Now, I want to read the value previously stored in sensor's internal memory using VL53L1X_GetOffset():
1) Without the above line of code:
VL53L1X_GetOffset() returns OFFSET = 1783 = 0x06F7 = 110 1111 0111 --> This is not right.
2) With the above line of code:
0x06F7 OR 0xF800 --> 0000 0110 1111 0111 OR 1111 1000 0000 0000 --> 1111 1110 1111 0111 = -265 --> This is now right. VL53L1X_GetOffset() return the same value that was calculated by VL53L1X_CalibrateOffset().