如何使用多个VL6180 TOF传感器?

时间:2018-07-17 17:39:02

标签: arduino sensor i2c lidar

我正在尝试通过I2C总线将两个Sparkfun VL6180 TOF传感器连接到Arduino板。我能够分别从两个传感器读取数据,但是如果两个传感器都连接到I2C总线,则无法从两个传感器读取数据。

当两个传感器都连接时,我可以从单个传感器读取该值。当我尝试使用I2C扫描仪查找两个传感器的地址时,只能找到一个传感器的地址,即默认的0x29。我可以单独读取传感器的地址,但是两者都有相同的地址。有人知道如何解决该问题吗?

I2C扫描器代码:

#include <Wire.h>
#include <Arduino.h>

// scans devices from 50 to 800KHz I2C speeds.
// lower than 50 is not possible
// DS3231 RTC works on 800 KHz. TWBR = 2; (?)
long speed[] = {
  50, 100, 200, 250, 400, 500, 800
};
const int speeds = sizeof(speed) / sizeof(speed[0]);

// DELAY BETWEEN TESTS
#define RESTORE_LATENCY  5    // for delay between tests of found devices.
bool delayFlag = false;

// MINIMIZE OUTPUT
bool printAll = true;
bool header = true;

// STATE MACHINE
enum states {
  STOP, ONCE, CONT, HELP
};
states state = STOP;

uint32_t startScan;
uint32_t stopScan;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  displayHelp();
}

void loop() {
  switch (getCommand()) {
    case 's':
      state = ONCE;
      break;
    case 'c':
      state = CONT;
      break;
    case 'd':
      delayFlag = !delayFlag;
      Serial.print(F("<delay="));
      Serial.println(delayFlag ? F("5>") : F("0>"));
      break;
    case 'e':
      // eeprom test TODO
      break;
    case 'h':
      header = !header;
      Serial.print(F("<header="));
      Serial.println(header ? F("yes>") : F("no>"));
      break;
    case '?':
      state = HELP;
      break;
    case 'p':
      printAll = !printAll;
      Serial.print(F("<print="));
      Serial.println(printAll ? F("all>") : F("found>"));
      break;
    case 'q':
      state = HELP;
      break;
    default:
      break;
  }

  switch (state) {
    case ONCE:
      I2Cscan();
      state = HELP;
      break;
    case CONT:
      I2Cscan();
      delay(1000);
      break;
    case HELP:
      displayHelp();
      state = STOP;
      break;
    case STOP:
      break;
    default: // ignore all non commands
      break;
  }
}

char getCommand() {
  char c = '\0';
  if (Serial.available()) {
    c = Serial.read();
  }
  return c;
}

void displayHelp() {
  Serial.println(F("\nArduino I2C Scanner - 0.1.03\n"));
  Serial.println(F("\ts = single scan"));
  Serial.println(F("\tc = continuous scan - 1 second delay"));
  Serial.println(F("\tq = quit continuous scan"));
  Serial.println(F("\td = toggle latency delay between successful tests."));
  Serial.println(F("\tp = toggle printAll - printFound."));
  Serial.println(F("\th = toggle header - noHeader."));
  Serial.println(F("\t? = help - this page"));
  Serial.println();
}

void I2Cscan() {
  startScan = millis();
  uint8_t count = 0;
  if (header) {
    Serial.print(F("TIME\tDEC\tHEX\t"));
    for (uint8_t s = 0; s < speeds; s++) {
      Serial.print(F("\t"));
      Serial.print(speed[s]);
    }
    Serial.println(F("\t[KHz]"));
    for (uint8_t s = 0; s < speeds + 5; s++) {
      Serial.print(F("--------"));
    }
    Serial.println();
  }
  // TEST
  // 0.1.04: tests only address range 8..120
  // --------------------------------------------
  // Address  R/W Bit Description
  // 0000 000   0 General call address
  // 0000 000   1 START byte
  // 0000 001   X CBUS address
  // 0000 010   X reserved - different bus format
  // 0000 011   X reserved - future purposes
  // 0000 1XX   X High Speed master code
  // 1111 1XX   X reserved - future purposes
  // 1111 0XX   X 10-bit slave addressing
  for (uint8_t address = 8; address < 120; address++) {
    bool printLine = printAll;
    bool found[speeds];
    bool fnd = false;
    for (uint8_t s = 0; s < speeds ; s++) {
      TWBR = (F_CPU / (speed[s] * 1000) - 16) / 2;
      Wire.beginTransmission (address);
      found[s] = (Wire.endTransmission () == 0);
      fnd |= found[s];
      // give device 5 millis
      if (fnd && delayFlag) delay(RESTORE_LATENCY);
    }
    if (fnd) count++;
    printLine |= fnd;
    if (printLine) {
      Serial.print(millis());
      Serial.print(F("\t"));
      Serial.print(address, DEC);
      Serial.print(F("\t0x"));
      Serial.print(address, HEX);
      Serial.print(F("\t"));
      for (uint8_t s = 0; s < speeds ; s++) {
        Serial.print(F("\t"));
        Serial.print(found[s] ? F("V") : F("."));
      }
      Serial.println();
    }
  }
  stopScan = millis();
  if (header) {
    Serial.println();
    Serial.print(count);
    Serial.print(F(" devices found in "));
    Serial.print(stopScan - startScan);
    Serial.println(F(" milliseconds."));
  }
}

从两个传感器读取数据的代码:

#include <Wire.h>
#include <SparkFun_VL6180X.h>

#define VL6180X_ADDRESS1 0x29
#define VL6180X_ADDRESS2 0x30

VL6180xIdentification identification1;
VL6180xIdentification identification2;
VL6180x sensor1(VL6180X_ADDRESS1);
VL6180x sensor2(VL6180X_ADDRESS2);

void setup() {
  Serial.begin(115200);
  Wire.begin();
  delay(100);
  sensor1.getIdentification(&identification1); // Retrieve manufacturer info from device memory
  printIdentification(&identification1);
  sensor2.getIdentification(&identification2); // Retrieve manufacturerinfo from device memory
  printIdentification(&identification2);
  if (sensor1.VL6180xInit() != 0) {
    Serial.println("S1FAILED TO INITALIZE");
  };
  if (sensor2.VL6180xInit() != 0) {
    Serial.println("S2FAILED TO INITALIZE");
  };
  sensor1.VL6180xDefautSettings();
  sensor2.VL6180xDefautSettings();//Load default settings to get started.
  delay(1000); // delay 1s
}

void loop() {
  Serial.print(" S1 :Distance measured (mm) = ");
  Serial.println( sensor1.getDistance() );
  Serial.print(" S2 :Distance measured (mm) = ");
  Serial.println( sensor2.getDistance() );
  delay(500);
};

void printIdentification(struct VL6180xIdentification *temp) {
  Serial.print("Model ID = ");
  Serial.println(temp->idModel);
  Serial.print("Model Rev = ");
  Serial.print(temp->idModelRevMajor);
  Serial.print(".");
  Serial.println(temp->idModelRevMinor);
  Serial.print("Module Rev = ");
  Serial.print(temp->idModuleRevMajor);
  Serial.print(".");
  Serial.println(temp->idModuleRevMinor);
  Serial.print("Manufacture Date = ");
  Serial.print((temp->idDate >> 3) & 0x001F);
  Serial.print("/");
  Serial.print((temp->idDate >> 8) & 0x000F);
  Serial.print("/1");
  Serial.print((temp->idDate >> 12) & 0x000F);
  Serial.print(" Phase: ");
  Serial.println(temp->idDate & 0x0007);
  Serial.print("Manufacture Time (s)= ");
  Serial.println(temp->idTime * 2);
  Serial.println();
  Serial.println();
}

1 个答案:

答案 0 :(得分:0)

如果传感器具有相同的I2C地址,并且无法配置该地址,则可能会出现问题,因为无法同时读取这两个地址。

首先研究配置I2C地址的可能性。许多I2C设备都有此选项。

如果这不可用,您可以做的就是将传感器的Vcc引脚连接到Arduino的数字引脚。当您要从传感器读取数据时,可以通过将另一个传感器的Vcc数字引脚设置为LOW来关闭另一个传感器,并通过将其Vcc数字引脚设置为HIGH来打开要读取的传感器。

但是,根据传感器的类型,您可能必须等待直到传感器准备就绪。某些传感器在打开时会花费一些时间才能提供准确的读数。