News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

VL53L1X Lidar module

Started by david, Aug 25, 2023, 09:09 AM

Previous topic - Next topic

david

Hi All,
I recently bought a tiny Lidar module just because I'm a sucker for playing with cheap sensors but this one is proving a bit frustrating.
As some of you will know, there is no published register map or basic procedure for setting up the device and instead ST provide an api.  Now I found some code relating to the device posted by Craig about 18 months ago-
https://protoncompiler.com/index.php/topic,619.msg6541.html#msg6541    (Post #17)
After adding the necessary set up for the 12F1840 chip I wanted to use I ran the code and the compiler complained that Buffer Array had not been defined so I added - Dim Buffer Array[12] as Word.
The compiler then produced a rash of errors as in the attached below yet nowhere have I used TrisB or PortB and the 12F1840 has no PortB.  Any thoughts where these have come from?

Cheers,
David

RGV250

Hi David,
How about posting the code you have which causes the error?

Bob

david

Code as follows-

'
'                  Vin <1 U 8> Gnd   
'    RS232         RA5 <2   7> RA0  AN0
'    Spare I/O     RA4 <3   6> RA1  SCL    10k pullups on board to Vin
'   Spare input    RA3 <4   5> RA2  SDA              "


Device = 12F1840
Config1 FCMEN_OFF, IESO_OFF, CLKOUTEN_OFF, BOREN_OFF, CPD_OFF, CP_OFF, MCLRE_OFF, PWRTE_ON, WDTE_OFF, FOSC_INTOSC
Config2 LVP_OFF, BORV_19, STVREN_OFF, PLLEN_OFF, WRT_OFF

Declare Xtal = 16 'Internal OSC
OSCCON = %01111010    '16MHz=01111010, 4MHz=01101010, 8MHz =01110010
TRISA = %00000110     '
ADCON0=%00000000     '
ADCON1=%00000000           '
Declare Hbus_Bitrate 400    '100kHz, 400kHz, 1000kHz
SSPCON1=%00111000       'enable port, 7 bit address, master mode
Symbol Lidar_W= %1010010  'OLED address and write
Symbol Lidar_R= %1010011  'OLED address and read 


    Dim J As Byte
    Dim DatoVL As Byte
    Dim DatoSensor[12] As Byte
    Dim Distance As Word
    Dim DistL As Word
    Dim DistFlag As Byte                            ' Flag Used to See When VLX53L0x Has been filled with a Distance to go to TX
    Dim devError As Byte
    Dim SPAD As Float
    Dim Signal As Word
    Dim Ambient As Word
    Dim DisRest As Word                             ' Load VL53L0X "DISTANCE" from (mm) into (cm) Held in "DisRest"
    Dim BufferArray[12] As Word

'-----------------------------------------------------------------------------------------------
' VL53L0X TOF Sensor
' XSHUNT Pin Must Go (HIGH +5V) To Enable Sensor or (LOW 0V) To Switch Sensor OFF
'===============================================================================================
    VL53Lx:
'System Range Start
    HBusOut Lidar_W,[$00,$01]
    DelayMS 5

'Range status
    HBusOut Lidar_W,[$14]
    DelayMS 5

' Read The 12 Bit Raw Data Of The VL53L0x Sensor:
    HBusIn Lidar_R,[Str DatoSensor]


  For J = 0 To 11
        BufferArray[J] = (DatoSensor[10]*256) + DatoSensor[11]   ' Fill All 12 Elements of the BufferArray With Distance Measurements from VL53L0X
        DistL = BufferArray[J]                                   ' Load BufferArray J Elements into DistL Variable
        Distance =  DistL                                        ' Push DistL Variable into the Distance Variable
  Next J
 
'-----------------------------------------------------------------------------------------------

' Resolve info of sensor VL53L0x:
'===============================================================================================
 
' Effective SPAD Return Count
    SPAD = DatoSensor[2] + DatoSensor[3]/255

' Signal Rate
    Signal = DatoSensor[6]*256 + DatoSensor[7]

' Ambient Rate
    Ambient = DatoSensor[8]*256 + DatoSensor[9]

' Display Output Data:
    Print At 1,6,"D: ",Dec Distance,"  "         ' Print Distance in mm
    HRSOut "VL: ", Dec3 Distance,"  "            ' PC TESTING
 
 Return

'-------------------------------------------------------------------
' Read VL53L0x Sensor Info
'-------------------------------------------------------------------
 Info_VL53:

'IDENTIFICATION REVISION ID
    HBusIn Lidar_R,$C2,[DatoVL]
                                                               

'IDENTIFICATION MODEL ID
    HBusIn Lidar_R,$C0,[DatoVL]
 
'PRE RANGE CONFIG VCSEL PERIOD
    HBusIn Lidar_R,$50,[DatoVL]

'FINAL RANGE CONFIG VCSEL PERIOD
    HBusIn Lidar_R,$70,[DatoVL]

Return
End

david

Maybe it wasn't complete code - there seems to be little or no set up unless it relies on defaults.
There's a heap of Arduino code out there but tracking down some of the elusive inc files is near impossible or they are only in hex.
I shall keep looking - this is just a play thing anyway.

David

david

OK - I think I've found the culprit.   There's a Print statement in the code which I haven't pruned out when I use my own OLED code.  I think the Print command assumes PortB.   With it remed out it does compile without errors.

David

Yves

It often happen to me when I'm stuck with a problem and I start writing my long story to the forum and in a flash I pick up my mistake or omission then cancel the message. It is often we are too exited to see the results and don't think properly and calmly.

Yves
Yves

david

Indeed yes.  I went through the code carefully and even used the editor's "find" function which couldn't detect PORTB or TRISB.  Shortly after pressing send I spotted the Print command and vaguely remembered that it may default to PortB.   
I was going to use a serial output anyway but it did compile when removed.  That is not to say it worked.  I have no idea if that was complete working code or a snippet only.  I'm sure the device is great but the documentation is awful and I'm totally lost without a register map.  It may end up in my drawer along with other "follies" gathered over the years.

Cheers,
David

Craig

Hi David

Only saw your post now, that code does work which you referred to but is written for the VL53L0X you have a 1X I think there is a slight difference between them just check the data sheets to see.
They work well but are very sensitive to UV Light. There are newer devices from ST which are much better in this range for UV Light but they are a different animal. 

Regards
Craig

david

Craig - many thanks for your reply.
Yes I have the VL53L1X and wasn't sure if it was different in its registers or just had a different beamwidth and longer range.
There was some mention of a misplaced Return.  (See_Mos?) There are two sections followed by a Return but I couldn't see where either was called from.  Perhaps I'm getting a bit old for this stuff but I found this sensor much more difficult to understand than any barometer, mag sensor or accelerometer module.   I shall go back and play spot the difference between the two models.

Cheers,
David

david

Hi All,
After several days trawling through github, Adafruit, Arduino, Pololu and others I'm still unable to get much sense out of my lidar module due to not being able to positively identify some key register addresses.  I'm fairly certain the VL53L0X and VL53L1X register maps are different even though they only mention the longer range of the latter when talking differences.  I struggle with C and C++ and while I can sort of follow the code I can't always link a command like "getDistance" back to an actual register address.
If anyone who has actually got a VL53L1X working can have a look at my efforts to date, I would much appreciate it.  Never again would I take on a small module that doesn't have a makers register map.

    Dim Distance As Word
    PORTA.0=0

VL53L1x:
    DelayMS 100
    PORTA.0=1         'enable Lidar chip
    DelayMS 100

    HBusOut Lidar_W,$00,[$00]   'soft reset
    DelayMS 10
                   
    HBusOut Lidar_W,$0B,[$00]   'sys init ?????
    DelayMS 10                     
   
    HBusOut Lidar_W,$86,[$00]   'clear interrupt
    DelayMS 10
   
    HBusOut Lidar_W,$87,[$00]   'start ranging
    DelayMS 100
   
    HBusIn Lidar_R,$96,[Distance]
   
    SerOut PORTA.5,84,[Dec Distance,13,10]
    HBusOut Lidar_W,[$86,$00]   'clear interrupt
    DelayMS 10
    PORTA.0=0        'disable chip
DelayMS 1000
GoTo VL53L1x
End


I should add that I can read the chip's ID so it confirms the I2C comms is working and the Lidar chip has booted.

Cheers,
David

tumbleweed

How are you reading the ID?

From looking at the Pololu cpp code, each transaction requires at least 3 bytes in addition to the chip I2C address... some require more. Register addresses are sent as 16-bit (high byte, low byte).

david

#11
Hi,
For reading the Sensor ID I did a two byte read from address 0x010F which returned 0xEACC but I then realised that the sensor ID is only a single byte value (0xEA) and I had actually appended the Module Type ID value (0xCC).  Both these values were confirmed in some document I will never be able to find again....
This is not to be confused with the Module ID at 0x0112 which is a two byte value.
Many of the Writes to the device are a single byte such as I2C Address+Write bit, target register, byte value.  Reads return mainly one and two byte values.

In the Pololu examples/continuous code it has-
 if (!sensor.init())
  {
    Serial.println("Failed to detect and initialize sensor!");
    while (1);

The term "sensor.init" is a key function but nowhere could I link that to an actual register.

Similarly the use of -
Serial.print(sensor.read());
I could not determine which register the term "sensor.read" was referring to.

I'll throw a bit more time at but it would be quicker for me to use an Arduino Uno, load the Pololu files and read the I2C traffic it uses.  That would then be easy to convert to Positron.

Cheers,
David

tumbleweed

#12
QuoteMany of the Writes to the device are a single byte such as I2C Address+Write bit, target register, byte value
Right, but the 'target register' address is a 16-bit value, so each write takes at least 4 bytes total when you include the device I2C addr:
[I2C_ADDR] [REG_ADDR_HIGH] [REG_ADDR_LOW] [DATA8]

Word writes and other functions will take more.

The code you're showing post #9 is only trying to write a single byte for the addr, so the "data byte" you're sending is actually the second part of the address.
In the Pololu file VL53L1X.cpp, an 8-bit register write looks like:
// Write an 8-bit register
void VL53L1X::writeReg(uint16_t reg, uint8_t value)
{
  bus->beginTransmission(address);
  bus->write((uint8_t)(reg >> 8)); // reg high byte
  bus->write((uint8_t)(reg));      // reg low byte
  bus->write(value);
  last_status = bus->endTransmission();
}

QuoteThe term "sensor.init" is a key function but nowhere could I link that to an actual register.
It's not a single register, it's a function (assuming 'sensor' is an instance of the VL53L1X class). It's defined in the Pololu file VL53L1X.cpp

bool VL53L1X::init(bool io_2v8)

All the register addresses used in that file are defined in  VL53L1X.h
   // register addresses from API vl53l1x_register_map.h
    enum regAddr : uint16_t
    {
      SOFT_RESET                                                    = 0x0000,
      I2C_SLAVE__DEVICE_ADDRESS                        = 0x0001,
      ANA_CONFIG__VHV_REF_SEL_VDDPIX            = 0x0002,
      ANA_CONFIG__VHV_REF_SEL_VQUENCH        = 0x0003,
      ANA_CONFIG__REG_AVDD1V2_SEL                 = 0x0004,
etc

david

Thanks so much for your reply - yes that makes total sense and also offers a glimmer of hope for me.  What a stuff up!  It never occurred to me when looking at register lists that they were all 2 byte addresses.
Right now I was trying to get an Arduino Nano to load the Pololu code but I'm not familiar with Arduino stuff and that's also not working.  You post means I can swing back to what I'm familiar with.
Thanks again.

David

Pepe

This is the VL53L1X library in C

tumbleweed

#15
Quote from: Pepe on Sep 02, 2023, 01:54 PMThis is the VL53L1X library in C
Unfortunately, all the low-level details are missing in that implementation and are left to the developer, so I don't know how much help that is.

For example, no where does it show you how to read/write registers...
int8_t VL53L1_WrByte(uint16_t dev, uint16_t index, uint8_t data) {
    return 0; // to be implemented
}

The pdf does have a description of using the device along with the VL53L1X_api.c file, so that could be handy.
At least you can see an overview of the steps involved, just not the low-level details.

Quote...I could not determine which register the term "sensor.read" was referring to.
I think you're going to find that many/all the routines require multiple steps so there's not many simple "read/write register" type of  operations.



david

It's getting very late here but I did try changing the register addresses to 2 byte values but still no life.
I can understand now why I managed to read the model ID - that was a two byte address (0x010F).
I have downloaded a heap of documentation from Arduino, Adafruit, Pololu - mainly C and C++ but also some Python and Linux.  It's still rather cryptic to me. My son tried to help but he's in Germany and he said he didn't think he could explain OO programming in a 10 minute chat session. I shall try again in the morning and at least I have a bit more confidence that the addressing is correct even if some registers are wrong or instructions are incomplete.

Cheers,
David

david

I finally got my Lidar module running but sadly on an Arduino Nano clone.  This has allowed me to use a small logic analyser to see what is going on and for both the Spark Fun and Adafruit libraries it's a lot busier than I expected.  I suspect almost all code is based closely on the ST api with few wanting to step off the safe path.
There are a few bytes of set up followed by writing 91 configuration values to consecutive addresses.  This was called "Simple Test" by Spark Fun and I was expecting it to use default values (no configuration) which should give 4000mm range and 10Hz updates. 
I was surprised also that they write all of the 91 addresses when the chip data clearly indicates it's not required -

"The interface also supports auto-increment indexing. After the first data byte has been
transferred, the index is automatically incremented by 1. The master can therefore send
data bytes continuously to the slave until the slave fails to provide an acknowledge or the
master terminates the write communication with a stop condition. If the auto-increment
feature is used the master does not have to send address indexes to accompany the data
bytes."

91 consecutive addresses x (device address + 2 byte register address) = 273 bytes not needed.  Why? I've done this before on Silabs Multisynth chips and it's always worked well.
I'm still unravelling the beginning and end code but this is quite small.   I also need to confirm if the device can run without configuration, even if accuracy is compromised somewhat.  Maybe one day I can share some working Positron code.

Cheers,
David

top204

#18
I've ordered a VL53L1X board from some of the money kindly donated by Gary (Bravo here on the forum), and will try and create a library file for it that can actually be understood and used. :-) Many thanks Gary, and your workbench looks wonderful in the picture you sent.

The trouble with the C++ users is that they have a tendency to copy a manufacturer's source code that is written for a Linux system on a single board unit and only make the changes for the pins used, or some changes to a peripheral's operation, so the code is extremely bulky and very over complex and not really suitable for a microcontroller, unless it is a 32-bit type. Also, decent comments seem to be a no-no in most library source codes for some inexplicable reason?

When the board arrives I'll get into it. Hopefully, I should have my workshop/office completed enough to move into it so I can create more for the compilers and get on with my life and get the upgrade finished with the new devices etc... I just need a bit more wood for the benches and desk. The racks are now completed, again, thanks to Gary's donation for the wood. Sitting here in the bedroom on my small cluttered desk is not a good place to get the imagination and creation juices flowing.



LeonJ

I "translated" these procs for the TimeOfFlight (TOF) sensor. As I remember, it all worked okay.
Hope it helps someone.