激光雷达传感器无法正常工作 - 如何在 arduino 上通过 I2C 使用两个激光雷达传感器

Lidar Sensors not working properly - How to work with two lidar Sensors over I2C on arduino

我目前正在与一些朋友一起开展一个项目,该项目是关于基于 ARDUINO 和 GARMIN Lidar v3HP 的激光雷达测量,我们正在从传感器中获得一些有问题的读数。它们似乎有效,但测量结果不正确。

我们的数据和地址都有问题,我们为传感器设置了两个不同的地址 0x42 和 0x43,但其中一个传感器保持默认地址。

#include <Arduino.h>
#include <Wire.h>
#include <stdint.h>
#include <LIDARLite_v3HP.h>
#include <I2CFunctions.h>

#define POWER_ENABLE_S1 12
#define POWER_ENABLE_S2 11
#define DEFAULT_ADDRESS 98
#define FAST_I2C
#define NUMERO_LIDARS 2

LIDARLite_v3HP Sensor1;
LIDARLite_v3HP Sensor2;


int detectedAddreses[NUMERO_LIDARS];
int currentAdd;
int deviceCount = 0;
int i = 0;

void scanI2C()
{
    int nDevices = 0;
    while (i < NUMERO_LIDARS)
    {
        for (byte addr = 1; addr < 127; ++addr)
        {
            Wire.beginTransmission(addr);
            byte error = Wire.endTransmission();
            if (error == 0)
            {
                Serial.print("Se encontro un dispositivo en ");                
                Serial.print(addr);
                Serial.println("  !");
                ++nDevices;
                detectedAddreses[i] = addr;
                if (addr == DEFAULT_ADDRESS)
                {
                    configSensors(i, 66 + deviceCount, addr);
                    detectedAddreses[i] = addr;
                    i++;
                }else{
                  detectedAddreses[i] = addr;
                  i++;
                }
            }
            else if (error == 4)
            {
                Serial.print("Error desconocido en ");
                Serial.println(addr);
            }
        }
        if (nDevices == 0)
        {
            Serial.println("No se encontraron dispositivos\n");
        }
        else
        {
            Serial.println("Terminado\n");
        }
    }
}

void configSensors(int sensor, uint8_t new_address, uint8_t old_address)
{
    switch (sensor)
    {
    case 0:
        Sensor1.setI2Caddr(new_address, 0, old_address);
        digitalWrite(POWER_ENABLE_S1, LOW);
        //detectedAddreses[sensor] = new_address;
        deviceCount++;
        Sensor1.configure(0,new_address);
        break;

    case 1:
        Sensor2.setI2Caddr(new_address, 0, old_address);
        digitalWrite(POWER_ENABLE_S2, LOW);
        //detectedAddreses[sensor] = new_address;
        deviceCount++;
        Sensor2.configure(0,new_address);
        i = 999;
        break;

    case 2:
        break;
    }
}

void setup()
{
    Serial.begin(115200);
    #ifdef FAST_I2C
        #if ARDUINO >= 157
            Wire.setClock(400000UL); // Set I2C frequency to 400kHz (for Arduino Due)
        #else
            TWBR = ((F_CPU / 400000UL) - 16) / 2; // Set I2C frequency to 400kHz
        #endif
    #endif
    pinMode(POWER_ENABLE_S1, OUTPUT);
    pinMode(POWER_ENABLE_S2, OUTPUT);
    digitalWrite(POWER_ENABLE_S1, HIGH);
    digitalWrite(POWER_ENABLE_S2, HIGH);
    Wire.begin();
    scanI2C();
    digitalWrite(POWER_ENABLE_S1,HIGH);
    digitalWrite(POWER_ENABLE_S2,HIGH);
    Sensor1.configure(3,detectedAddreses[0]);
    Sensor2.configure(3,detectedAddreses[1]);
}

void measure(){
  float s1;
  float s2;  
  Sensor1.waitForBusy();
  Sensor1.takeRange();
  Sensor1.waitForBusy();
  s1 = Sensor1.readDistance(detectedAddreses[0]);  
  Sensor2.waitForBusy();
  Sensor2.takeRange();
  Sensor2.waitForBusy();
  s2 = Sensor2.readDistance(detectedAddreses[1]);
  Serial.println("Sensor 1: " + String(s1) + "; Sensor 2: " + String(s2));
  }

void loop()
{
 /*Serial.println(detectedAddreses[0]);
 Serial.println(detectedAddreses[1]);*/
measure();
  
}

根据您的热门评论,同时配置两个激光雷达可能存在问题。

在出厂默认情况下,它们将两者 响应默认 I2C 地址 0x62。因此,当您尝试一次重新配置 one 时,它们将 both 响应 [并且可能存在竞争条件] 并且 两个都被编程到新的I2C地址。

If[这是一个很大的if]激光雷达可以将配置保存到单元上的非易失性存储器中,您可以连接one 一次 [physically/manually] 并给他们不同的地址。本机保存地址。并且,下一次,将只响应“新”地址。

然后,在重新配置两个单元后,您可以同时连接两个单元,它们将[根据需要]单独响应。

我看了 .pdf 和接线图。您可以将激光雷达的电源引脚 [或启用引脚] 连接到 Arduino GPIO 端口引脚(而不是 +5V)。然后,您可以单独控制每个单元的电源。然后,您可以像上面那样重新配置两者。也就是说,断言一个电源,重新配置它,关闭它 [使用保存的配置]。对另一个单元执行此操作。然后,您可以启动两个单元[此时,它们正在响应不同的 I2C 地址]。

不知道 Garmin 是否立即启动激光器,或者您是否必须给它一个“启动”命令。如果没有没有单独的启动命令,能够单独控制电源可能是一件好事。

我不熟悉 Garmin 的激光雷达,但我写了 S/W 来控制 Velodyne 激光雷达,我们不得不以交错的方式施加电源,因为当它们 启动会使系统“断电”。与 Garmin,YMMV。

如果一切都失败了,您可能必须将每个单元放在 separate/different 物理 I2C 总线上 [因为您无法单独重新配置它们]。

这是工作代码,

传感器连接在同一 I2C 总线上,每个传感器的电源启用引脚和接地连接到 arduino。传感器的电源由 11.1V 电池提供,电源调节器为 5V

#include <Arduino.h>
#include <Wire.h>
#include <stdint.h>
#include <LIDARLite_v3HP.h>
#include <I2CFunctions.h>

#define POWER_ENABLE_S1 12
#define POWER_ENABLE_S2 11
#define DEFAULT_ADDRESS 98
#define FAST_I2C
#define NUMERO_LIDARS 2

LIDARLite_v3HP Sensor1;
LIDARLite_v3HP Sensor2;


int detectedAddreses[NUMERO_LIDARS];
int currentAdd;
int deviceCount = 0;
int i = 0;

void scanI2C()
{
    int nDevices = 0;
    while (i < NUMERO_LIDARS)
    {
        for (byte addr = 1; addr < 127; ++addr)
        {
            Wire.beginTransmission(addr);
            byte error = Wire.endTransmission();
            if (error == 0)
            {
                Serial.print("Se encontro un dispositivo en ");                
                Serial.print(addr);
                Serial.println("  !");
                ++nDevices;
                detectedAddreses[i] = addr;
                if (addr == DEFAULT_ADDRESS)
                {
                    configSensors(i, 66 + deviceCount, addr);
                    detectedAddreses[i] = addr;
                    i++;
                }else{
                  detectedAddreses[i] = addr;
                  i++;
                }
            }
            else if (error == 4)
            {
                Serial.print("Error desconocido en ");
                Serial.println(addr);
            }
        }
        if (nDevices == 0)
        {
            Serial.println("No se encontraron dispositivos\n");
        }
        else
        {
            Serial.println("Terminado\n");
        }
    }
}

void configSensors(int sensor, uint8_t new_address, uint8_t old_address)
{
    switch (sensor)
    {
    case 0:
        Sensor1.setI2Caddr(new_address, 0, old_address);
        digitalWrite(POWER_ENABLE_S1, LOW);
        //detectedAddreses[sensor] = new_address;
        deviceCount++;
        Sensor1.configure(0,new_address);
        break;

    case 1:
        Sensor2.setI2Caddr(new_address, 0, old_address);
        digitalWrite(POWER_ENABLE_S2, LOW);
        //detectedAddreses[sensor] = new_address;
        deviceCount++;
        Sensor2.configure(0,new_address);
        i = 999;
        break;

    case 2:
        break;
    }
}

void setup()
{
    Serial.begin(115200);
    #ifdef FAST_I2C
        #if ARDUINO >= 157
            Wire.setClock(400000UL); // Set I2C frequency to 400kHz (for Arduino Due)
        #else
            TWBR = ((F_CPU / 400000UL) - 16) / 2; // Set I2C frequency to 400kHz
        #endif
    #endif
    pinMode(POWER_ENABLE_S1, OUTPUT);
    pinMode(POWER_ENABLE_S2, OUTPUT);
    digitalWrite(POWER_ENABLE_S1, HIGH);
    digitalWrite(POWER_ENABLE_S2, HIGH);
    Wire.begin();
    scanI2C();
    digitalWrite(POWER_ENABLE_S1,HIGH);
    digitalWrite(POWER_ENABLE_S2,HIGH);
    Sensor1.configure(3,detectedAddreses[0]);
    Sensor2.configure(3,detectedAddreses[1]);
}

void measure(){
  float s1;
  float s2;  
  digitalWrite(POWER_ENABLE_S1,HIGH);
  digitalWrite(POWER_ENABLE_S2,LOW);
  delay(25);
  Sensor1.waitForBusy();
  Sensor1.takeRange();
  Sensor1.waitForBusy();
  s1 = Sensor1.readDistance(detectedAddreses[0]);
  digitalWrite(POWER_ENABLE_S1,LOW);
  digitalWrite(POWER_ENABLE_S2,HIGH);  
  delay(25);
  Sensor2.waitForBusy();
  Sensor2.takeRange();
  Sensor2.waitForBusy();
  s2 = Sensor2.readDistance(detectedAddreses[1]);
  Serial.println("Sensor 1: " + String(s1) + "; Sensor 2: " + String(s2));
  }

void loop()
{
 /*Serial.println(detectedAddreses[0]);
 Serial.println(detectedAddreses[1]);*/
measure();
  
}