3 Lidar Lite sensors - Change address for I2C

I updated the code and implemented this statements for a better overview:

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

LIDARLite lidar_left;
LIDARLite lidar_front;
LIDARLite lidar_right;

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

#define UNIT_ID_HIGH 0x16 // Serial number high byte
#define UNIT_ID_LOW 0x17 // Serial number low byte
#define I2C_ID_HIGH 0x18 // Write serial number high byte for I2C address unlock
#define I2C_ID_LOW 0x19 // Write serial number low byte for I2C address unlock
#define I2C_SEC_ADDR 0x1a // Write new I2c address after unlock
#define I2C_CONFIG 0x1e // Default address response control

#define LIDAR_STD_ADDRESS 0x62 // Standard I2C-address for all sensors
#define LIDAR_LEFT_ADDRESS 0x41 // New I2C-address right
#define LIDAR_FRONT_ADDRESS 0x42 // New I2C-address front
#define LIDAR_RIGHT_ADDRESS 0x43 // New I2C-address left

void setup() {

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

  // define the enable Pin as Output
  pinMode(sensorLeft_EN, OUTPUT);
  pinMode(sensorFront_EN, OUTPUT);
  pinMode(sensorRight_EN, OUTPUT);
  
  // Turn off all sensors
  digitalWrite(sensorLeft_EN, LOW);
  digitalWrite(sensorFront_EN, LOW);
  digitalWrite(sensorRight_EN, LOW);

  // To change the I2C address, the unique serial number of the unit must be read and then
  // written back to the device before setting the new address. The process is as follows:

  // Turn on the right sensor
  digitalWrite(sensorRight_EN, HIGH);
  Serial.println("Right sensor turned on");

  // Step 1: Read the two byte serial number from 0x96 (high byte 0x16 and low byte 0x17)
  Wire.beginTransmission(LIDAR_STD_ADDRESS);
  Wire.write(0x96);
  Wire.requestFrom(LIDAR_STD_ADDRESS, 2); // 2 Bytes lesen, wie in der Anleitung angegeben
  byte highByte_Right = Wire.read();
  byte lowByte_Right = Wire.read();
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 1 right failed");

  // Step 2. Write the serial number high byte to 0x18
  Wire.beginTransmission(LIDAR_STD_ADDRESS);
  Wire.write(I2C_ID_HIGH);
  Wire.write(UNIT_ID_HIGH);
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 2 right failed");

  // Step 3: Write the serial number low byte to 0x19
  Wire.beginTransmission(LIDAR_STD_ADDRESS);
  Wire.write(I2C_ID_LOW);
  Wire.write(UNIT_ID_LOW);
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 3 right failed");

  // Step 4: Write the desired new I2C address to 0x1a
  Wire.beginTransmission(LIDAR_STD_ADDRESS);
  Wire.write(I2C_SEC_ADDR);
  Wire.write(LIDAR_RIGHT_ADDRESS);
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 4 right failed");

  // Step 5: Write 0x08 to 01e to disable the default address
  Wire.beginTransmission(LIDAR_RIGHT_ADDRESS);
  Wire.write(I2C_CONFIG);
  Wire.write(0x08);
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 5 right failed");

  // Print change message in serial monitor
  Serial.println("Address of right sensor changed");

  // Turn on front sensor (standard address)
  digitalWrite(sensorFront_EN, HIGH);

  Serial.println("Front sensor turned on");

  // Step 1: Read the two byte serial number from 0x96 (high byte 0x16 and low byte 0x17)
  Wire.beginTransmission(LIDAR_STD_ADDRESS);
  Wire.write(0x96);
  Wire.requestFrom(LIDAR_STD_ADDRESS, 2); // 2 Bytes lesen, wie in der Anleitung angegeben
  byte highByte_Front = Wire.read();
  byte lowByte_Front = Wire.read();
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 1 front failed");

  // Step 2. Write the serial number high byte to 0x18
  Wire.beginTransmission(LIDAR_STD_ADDRESS);
  Wire.write(I2C_ID_HIGH);
  Wire.write(UNIT_ID_HIGH);
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 2 front failed");

  // Step 3: Write the serial number low byte to 0x19
  Wire.beginTransmission(LIDAR_STD_ADDRESS);
  Wire.write(I2C_ID_LOW);
  Wire.write(UNIT_ID_LOW);
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 3 front failed");

  // Step 4: Write the desired new I2C address to 0x1a
  Wire.beginTransmission(LIDAR_STD_ADDRESS);
  Wire.write(I2C_SEC_ADDR);
  Wire.write(LIDAR_FRONT_ADDRESS);
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 4 front failed");

  // Step 5: Write 0x08 to 01e to disable the default address
  Wire.beginTransmission(LIDAR_FRONT_ADDRESS);
  Wire.write(I2C_CONFIG);
  Wire.write(0x08);
  Wire.endTransmission();
  if (!Wire.endTransmission()) Serial.println("Step 5 front failed");

  // Print change message in serial monitor
  Serial.println("Address of right sensor changed");

  // Configuration of the sensors
  lidar_right.begin(0, true); // Set configuration to default and I2C to 400 kHz
  lidar_right.configure(0); // Standard configuration
  lidar_front.begin(0, true);
  lidar_front.configure(0);

  Serial.println("Ready!");

  delay(2000);

}

void loop() {

  // Measure the distance and print it in the serial monitor
  Serial.print(lidar_right.distance());
  Serial.print(",");
  Serial.println(lidar_front.distance());

  delay(1000);

}

My serial monitor prints the error messages. Meaning all steps except 5 failed and the transmission of the message didn't work.

Right sensor turned on
Step 1 right failed
Step 2 right failed
Step 3 right failed
Step 4 right failed
Address of right sensor changed
Front sensor turned on
Step 1 front failed
Step 2 front failed
Step 3 front failed
Step 4 front failed
Address of right sensor changed
Ready!

I think I followed the correct procedure:

  1. Turn off all sensors
  2. Turn on one sensor and change its address
  3. Turn on the next sensor and change its address

I wrote the seperate steps in the code for a better overview, ChatGPT then corrected it so every step has its own beginTransmission and endTransmission. I think shouldn't be a problem and helps for a better overview of the single steps. Can you see what's wrong?

Until you have clearly demonstrated that you can change the address of one sensor, then use that sensor successfully, you are wasting your time with three of them.

Especially so with ChatGPT's help.

Delete the first Wire.endTransmission().

If you end the transmission and then try to end it again, it will always fail, I think.

No thanks, you seem to know everything.

Ladies and Gentleman, it worked!

I used the lidar setI2Caddr method instead of the wire library and it finally worked, very happy about it. This is the working code which I also sent to Garmin support, so they can post it in their GitHub.

Thanks everyone for helping out and I hope someday this can help others.

#include <WiFiS3.h>
#include "arduino_secrets.h"
#include <LIDARLite.h>  // Include the Lidar-Lite library
#include <Wire.h>

LIDARLite lidarLeft;
LIDARLite lidarFront;
LIDARLite lidarRight;

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

// LIDAR Sensor addresses
char lidarLeft_ADDR = 0x40;   // New address of left sensor
char lidarFront_ADDR = 0x42;  // New address of front sensor
char lidarRight_ADDR = 0x44;  // New address of right sensor

int left = 0;
int front = 0;
int right = 0;

unsigned long previousMillis = 0;
const long interval = 10;  // Interval in miliseconds between measurements
int counter = 0;

void setup() {

  Serial.begin(9600);  // Initialize serial communication

  Wire.begin();

  // Define the enable Pins as Output to be able to turn the sensors on and off
  pinMode(sensorLeft_EN, OUTPUT);
  pinMode(sensorFront_EN, OUTPUT);
  pinMode(sensorRight_EN, OUTPUT);

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

  // Turn on the left sensor and change its address
  digitalWrite(sensorLeft_EN, HIGH);
  delay(1000);
  lidarLeft.setI2Caddr(lidarLeft_ADDR, true);
  delay(1000);
  lidarLeft.configure(0, lidarLeft_ADDR);
  delay(1000);

  // Turn on the front sensor and change its address
  digitalWrite(sensorFront_EN, HIGH);
  delay(1000);
  lidarFront.setI2Caddr(lidarFront_ADDR, true);
  delay(1000);
  lidarFront.configure(0, lidarFront_ADDR);
  delay(1000);

  // Turn on the right sensor and change its address
  digitalWrite(sensorRight_EN, HIGH);
  delay(1000);
  lidarRight.setI2Caddr(lidarRight_ADDR, true);
  delay(1000);
  lidarRight.configure(0, lidarRight_ADDR);
  delay(1000);

  delay(5000);
}


void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    left = lidarLeft.distance(true, lidarLeft_ADDR);
    Serial.print(left);
    Serial.print(",");
    front = lidarFront.distance(true, lidarFront_ADDR);
    Serial.print(front);
    Serial.print(",");
    right = lidarRight.distance(true, lidarRight_ADDR);
    Serial.println(right);
  }
}

If you want, please comment some "key words" others might use when trying to find this thread.

I will post down here some information about our project for those interested, so you can see why we wanted to change these addresses.

All the best to all helpers and readers! :smiley:

So as mentioned, some insights on the project:

Our challenger is visually impaired since birth, but he fascinated of driving remote-controlled cars. We have to design him a system that allows him to use auditive feedback to manouver his car.
We use 3 lidar sensors, one in front and one left and right, about 45 degrees away. We measure the distance with a frequency of 100 Hertz and send this data in UDP packages. For that we make a WiFi-Access-Point on the Arduino.
A second Arduino reades these packages and generates a sound according to the measured distance, which will allow him to drive his car at high speeds while being stationary.

This is the code for the first Arduino:

#include <WiFiS3.h>
#include "arduino_secrets.h"
#include <LIDARLite.h> // Include the Lidar-Lite library
#include <Wire.h>

LIDARLite lidarLeft;
LIDARLite lidarFront;
LIDARLite lidarRight;

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

// New LIDAR Sensor addresses
char lidarLeft_ADDR = 0x40;   // New address of left sensor
char lidarFront_ADDR = 0x42;  // New address of front sensor
char lidarRight_ADDR = 0x44;  // New address of right sensor

int left = 0;
int front = 0;
int right = 0;

// WiFi credentials (saved in arduino_secrets.h)
char ssid[] = SECRET_SSID;      // Netzwerk SSID (Name)
char pass[] = SECRET_PASS;      // Netzwerk Passwort
unsigned int localPort = 65535;

int keyIndex = 0;               // Netzwerkschlüsselindexnummer (nur für WEP erforderlich)
int status = WL_IDLE_STATUS;    // WiFi Status
WiFiServer server(80);          // Erstellen Sie einen WiFi-Server auf Port 80

unsigned long previousMillis = 0;
const long interval = 10;  // Interval in miliseconds between measurements
int counter = 0;

WiFiUDP Udp;  // UDP-Objekt zum Senden von Sensordaten

void setup() {
  
  Serial.begin(9600);  // Initialisieren Sie die serielle Kommunikation

  Wire.begin();

  // Define the enable Pins as Output to be able to turn the sensors on and off
  pinMode(sensorLeft_EN, OUTPUT);
  pinMode(sensorFront_EN, OUTPUT);
  pinMode(sensorRight_EN, OUTPUT);

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

  // Turn on the left sensor and change its address
  digitalWrite(sensorLeft_EN, HIGH);
  delay(1000);
  lidarLeft.setI2Caddr(lidarLeft_ADDR, true);
  delay(1000);
  lidarLeft.configure(0, lidarLeft_ADDR);
  delay(1000);

  // Turn on the front sensor and change its address
  digitalWrite(sensorFront_EN, HIGH);
  delay(1000);
  lidarFront.setI2Caddr(lidarFront_ADDR, true);
  delay(1000);
  lidarFront.configure(0, lidarFront_ADDR);
  delay(1000);

  // Turn on the right sensor and change its address
  digitalWrite(sensorRight_EN, HIGH);
  delay(1000);
  lidarRight.setI2Caddr(lidarRight_ADDR, true);
  delay(1000);
  lidarRight.configure(0, lidarRight_ADDR);
  delay(1000);

  delay(5000);

  // Check connection of WiFi-module
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Kommunikation mit dem WiFi-Modul fehlgeschlagen!");
    while (true);
  }

  // Check firmware and upgrade if necessary
  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Bitte aktualisieren Sie die Firmware");
  }

  // configure WiFi with static IP
  WiFi.config(IPAddress(192, 48, 56, 2));

  // Begin setup of WiFi access point
  Serial.print("Erstelle Access Point mit dem Namen: ");
  Serial.println(ssid);
  status = WiFi.beginAP(ssid, pass);
  if (status != WL_AP_LISTENING) {
    Serial.println("Erstellen des Access Points fehlgeschlagen");
    while (true);
  }

  // Wait for access point setup
  delay(10000);

  // Begin UDP-communication
  Udp.begin(localPort);

  // Print WiFi-Status
  printWiFiStatus();

}

// Function to print the WiFi-status
void printWiFiStatus() {
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  IPAddress ip = WiFi.localIP();
  Serial.print("IP-Adresse: ");
  Serial.println(ip);
}

// Function to send data over WiFi-UDP
void sendSensorData() {
  char sensorData[20]; // Change this number for bigger packages
  
  // Measure the distance
  left = lidarLeft.distance(true, lidarLeft_ADDR);
  Serial.print(left);
  Serial.print(",");
  front = lidarFront.distance(true, lidarFront_ADDR);
  Serial.print(front);
  Serial.print(",");
  right = lidarRight.distance(true, lidarRight_ADDR);
  Serial.println(right);
  
  // Send the UDP package
  sprintf(sensorData, "%d,%d,%d", left, front, right);
  Udp.beginPacket("192.48.56.3", 65535);
  Udp.write(sensorData);
  Udp.endPacket();
  Serial.println(sensorData);
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    // Measure and send
    sendSensorData();

  }
}

The second Arduino:

#include <WiFi.h>
#include <WiFiUdp.h>

const char *ssid = "Arduino";          // Netzwerk SSID (Name)
const char *password = "ATC_2024";     // Netzwerk Passwort
const unsigned int localPort = 65535;  // Lokaler Port zum Empfangen

const int buzzerPin_left = 9;
const int buzzerPin_front = 6;
const int buzzerPin_right = 3;

WiFiUDP udp;

void setup() {

  Serial.begin(9600);
  pinMode(buzzerPin_left, OUTPUT);
  pinMode(buzzerPin_right, OUTPUT);
  pinMode(buzzerPin_right, OUTPUT);
  Serial.println("Verbindung zum WiFi herstellen");

  // configure WiFi with static IP
  WiFi.config(IPAddress(192, 48, 56, 3));

  // Connect to WiFi
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi verbunden");

  // Begin UDP
  udp.begin(localPort);
  Serial.println("UDP-Server gestartet");
}

void loop() {
  // Check for incoming data
  int packetSize = udp.parsePacket();
  if (packetSize) {
    // Read the package into a buffer
    char packetBuffer[packetSize];
    udp.read(packetBuffer, packetSize);

    // Extract sensor data from the package
    String packetData = String(packetBuffer);
    int comma1 = packetData.indexOf(',');
    int comma2 = packetData.indexOf(',', comma1 + 1);

    String leftStr = packetData.substring(0, comma1);
    String frontStr = packetData.substring(comma1 + 1, comma2);
    String rightStr = packetData.substring(comma2 + 1);

    int left = leftStr.toInt();
    int front = frontStr.toInt();
    int right = rightStr.toInt();

    Serial.print(left);
    Serial.print(",");
    Serial.print(front);
    Serial.print(",");
    Serial.println(right);

    // Tone for left sensor
    if (left < 50) {
      int toneDuration_left = left / 5;
      tone(buzzerPin_left, 1760);
      delay(toneDuration_left);
      noTone(buzzerPin_left);
    }

    // Tone for right sensor
    if (right < 50) {
      int toneDuration_right = right / 5;
      tone(buzzerPin_right, 2793);
      delay(toneDuration_right);
      noTone(buzzerPin_right);
    }

    // Ton for front sensor
    if (front < 100) {
      int toneDuration_front = front / 5;
      tone(buzzerPin_front, 4000);
      delay(toneDuration_front);
      noTone(buzzerPin_front);
    }
  }
}

The tone generation is not yet optimal, but we're working on it. I you have any suggestions, feel free to comment it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.