簡體   English   中英

激光雷達傳感器無法正常工作 - 如何在 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響應。 所以,當你試圖重新配置一次一個,他們將響應[並有可能成為一個競爭條件],它們都將得到編程,以新的I2C地址。

如果[這是一個很大的條件]激光雷達可以將配置保存到設備上的非易失性存儲中,您可以一次[物理/手動]連接一個,並為它們提供不同的地址。 本機保存地址。 並且,下一次,只會響應“新”地址。

然后,在重新配置兩個單元后,您可以同時連接兩個單元,它們將[根據需要]單獨響應。

我查看了.pdf和接線圖。 您可以將激光雷達的電源引腳 [或啟用引腳] 連接到 Arduino GPIO 端口引腳(而不是 +5V)。 然后,您可以單獨控制每個單元的加電。 然后,您可以按上述方式重新配置兩者。 也就是說,斷言一個電源,重新配置它,關閉它[使用保存的配置]。 對另一個單元執行此操作。 然后,您可以啟動兩個單元 [此時,它們響應不同的I2C 地址]。

不知道 Garmin 是立即啟動激光還是必須給它一個“啟動”命令。 如果沒有單獨的啟動命令,能夠單獨控制電源可能是一件好事。

我不熟悉的Garmin的激光雷達,但我已經寫了S / W來控制Velodyne激光雷達,我們不得不以交錯的方式,施加電力,因為當他們開始了將“掉電”系統的電源浪涌。 使用 Garmin,YMMV。

如果所有其他方法都失敗了,您可能必須將每個單元放在單獨/不同的物理 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();
  
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM