3 Lidar Lite sensors - Change address for I2C

Hello :slight_smile:

I am working on a project which includes 3 Lidar-Lite v3 sensors. These should measure distances and print them to serial monitor. I want to use I2C which allows to use multiple sensors and connect them to SCL and SDA. PWM didn't work, I already tried that.

All three sensors have the same standard address which I need to change. I searched the forum, but it didn't work and the provided discussions are already closed. These are the links to the discussions:
Lidar lite V3 - Change i2c address
2 Garmin Lidar-Lite Sensors using I2C
change address of LIDAR-Lite v3

According to one discussion, I need to turn off the sensors, turn one on, change its address and then to the same for the second one, so I don't change the address for all sensors. I tried to do this:

#include <Wire.h>
#include <LIDARLite.h>

LIDARLite lidarLeft;
LIDARLite lidarFront;
LIDARLite lidarRight;

byte serialNumber[2];

const int sensorLeft_EN = 8;
const int sensorFront_EN = 9;
const int sensorRight_EN = 10;

char UNIT_ID_HIGH = 0x16;
char UNIT_ID_LOW = 0x17;
char I2C_ID_HIGH = 0x18;
char I2C_ID_LOW = 0x19;
char I2C_SEC_ADDR = 0x1a;
char I2C_CONFIG = 0x1e;

// LIDAR Sensor addresses
char lidarStd_ADDR = 0x62;    // Default address
char lidarLeft_ADDR = 0x63;   // New address for left sensor
char lidarFront_ADDR = 0x64;  // New address for front sensor

void setup() {
  // Define the power source (orange cable) as output to turn on/off the sensors
  pinMode(sensorLeft_EN, OUTPUT);
  pinMode(sensorFront_EN, OUTPUT);
  pinMode(sensorRight_EN, OUTPUT);

  // Disable all sensors
  digitalWrite(sensorLeft_EN, LOW);
  digitalWrite(sensorFront_EN, LOW);
  digitalWrite(sensorRight_EN, LOW);

  Serial.begin(115200);  // Initialize serial connection

  Wire.begin();  // Connect to the I2C bus

  // Read serial number Left
  digitalWrite(sensorLeft_EN, HIGH);  // enable the left sensor
  uint8_t serialHigh, serialLow;      // 1. read the two byte serial number
  Wire.beginTransmission(lidarStd_ADDR);
  Wire.write(0x96);
  Wire.endTransmission(false);         // Don't release the bus
  Wire.requestFrom(lidarStd_ADDR, 2);  // Request 2 bytes
  if (Wire.available() >= 2) {
    serialHigh = Wire.read();
    serialLow = Wire.read();
  }

  // Write serial number to new address
  Wire.beginTransmission(lidarLeft_ADDR);
  Wire.write(0x18);  // Address to write high byte
  Wire.write(serialHigh);
  Wire.write(0x19);  // Address to write low byte
  Wire.write(serialLow);
  Wire.write(0x1A);  // Address to write new desired I2C address
  Wire.write(lidarLeft_ADDR);
  Wire.write(0x1E);  // Address to disable default address
  Wire.write(0x08);  // Value to disable default address
  Wire.endTransmission();

  digitalWrite(sensorLeft_EN, LOW);  // disable the left sensor

  // Read serial number Front
  digitalWrite(sensorFront_EN, HIGH);  // enable the front sensor
  Wire.beginTransmission(lidarStd_ADDR);
  Wire.write(0x96);
  Wire.endTransmission(false);         // Don't release the bus
  Wire.requestFrom(lidarStd_ADDR, 2);  // Request 2 bytes
  if (Wire.available() >= 2) {
    serialHigh = Wire.read();
    serialLow = Wire.read();
  }

  // Write serial number to new address
  Wire.beginTransmission(lidarFront_ADDR);
  Wire.write(0x18);  // Address to write high byte
  Wire.write(serialHigh);
  Wire.write(0x19);  // Address to write low byte
  Wire.write(serialLow);
  Wire.write(0x1A);  // Address to write new desired I2C address
  Wire.write(lidarFront_ADDR);
  Wire.write(0x1E);  // Address to disable default address
  Wire.write(0x08);  // Value to disable default address
  Wire.endTransmission();

  digitalWrite(sensorFront_EN, LOW);  // disable the front sensor

  // Enable all sensors
  digitalWrite(sensorLeft_EN, HIGH);
  digitalWrite(sensorFront_EN, HIGH);
  digitalWrite(sensorRight_EN, HIGH);

  // Set configuration to default and I2C to 400 kHz for all sensors
  lidarLeft.begin(0, true);
  lidarLeft.configure(0);
  lidarFront.begin(0, true);
  lidarFront.configure(0);
  lidarRight.begin(0, true);
  lidarRight.configure(0);
}

void loop() {
  // Read and print distance from all sensors
  Serial.print(lidarLeft.distance());
  Serial.print(",");
  Serial.print(lidarFront.distance());
  Serial.print(",");
  Serial.println(lidarRight.distance());

  delay(100);
}

Compiling works, but the monitor only shows 0,0,0

This is the documentation:
User_Manual.pdf (749,7 KB)

What did I do wrong?

Thank you very much that you took your time reading through this and hopefully help me.

All the best!

At this point, no device on the bus has that address.

First, change the address of one sensor, and verify that the operation was successful.

Thank you for your answer!
According to the documentation, this is the standard address every sensor has. That's why I turn off two sensors so I can change the address only on the one that it turned on. Or am I wrong?

What address is that?

For the line of code I referred to, what address is that transmitting to?

Thank you for your reply!
How can I verify this? I can't just print the address to the serial monitor, since the address is a const int.
For example:

Serial.print(lidarLeft_ADDR);

always gives me the correct address, correct?

Of course you can print the value of a constant int.

It looks like you are following the procedure described in the manual, but don't confuse the issue by starting with all three devices. Test the code with just one sensor before adding another.

This is the standard address of every sensor:

char lidarStd_ADDR = 0x62;    // Default address

image

I have a suggestion:

This function returns a value which tells you whether the transmission was successful or not. Each time your code uses this function, print an error message to Serial Monitor if it fails. Like this:

if (!Wire.endTransmission()) Serial.println("Transmission failed!!!");

In post #5, I asked 2 questions. You have answered only one of them.

I will try this!

Then I didn't understand the question. How do you mean which address it is transmitting to?

Yeah sure, I meant what is the point of printing it? If I print it, it will show the const int value regardless if the address change has worked. Or do I understand you wrong?

I will try it again with one sensor. If I change the address and call the sensor with the new one, it should return a value, if it didn't work I should get a >nack in the serial monitor

The line of code I pointed out on post #2. What address is that transmitting to? Is that the address of any device on the bus at that point in time?

Remember, at this point, your code has enabled one of the sensors, and it has the standard address. You want to change its address. But it's address hasn't changed yet. So what address should you transmit to in order to change the address?

Hi, @tropfenderwasserhahn

Have you been able to communicate with JUST one Lidar, to prove your hardware?

If not, then I suggest you do that basic operation first.
Forget about address changing and isolating one lidar from the others for the moment.

Tom.. :smiley: :+1: :coffee: :australia:

The information is on page 5 of the pdf manual you supplied.
Perhaps you need to select something more user friendly to your level of knowledge.

I think I now understand what you mean.
This is the standard address:

char lidarStd_ADDR = 0x62;    // Default address

Then all sensors, which still have this same standard address are turned off:

  digitalWrite(sensorLeft_EN, LOW);
  digitalWrite(sensorFront_EN, LOW);
  digitalWrite(sensorRight_EN, LOW);

I enable one and read its address:

  digitalWrite(sensorLeft_EN, HIGH);  // enable the left sensor
  uint8_t serialHigh, serialLow;      // 1. read the two byte serial number
  Wire.beginTransmission(lidarStd_ADDR);
  Wire.write(0x96);
  Wire.endTransmission(false);         // Don't release the bus
  Wire.requestFrom(lidarStd_ADDR, 2);  // Request 2 bytes
  if (Wire.available() >= 2) {
    serialHigh = Wire.read();
    serialLow = Wire.read();
  }

Here I think I made a mistake:

  Wire.write(0x96);

I have to read the serial number from 0x96, not write it to. The transmission doen't get ended. But then in the next sequence, I try to begin the transmission to a sensor with an address, that doesn't yet exist, because I haven't changed it yet.

  Wire.beginTransmission(lidarLeft_ADDR);

Since the transmission hasn't ended above, I can delete this line and change the address.

I hope I understood your help correctly! Thank you!

Hi Tom. Yes, fortunately that worked.

Unfortunately, that is not an option.
Reading your comment I guess that you understand the problem? Could you point out for me which section of the code I did wrong according to the manual?

I don't know if that is an error.

Exactly!