title: How to use multiple VL6180 TOF sensors?
body: <p>I am trying to connect two Sparkfun VL6180 TOF sensors to an Arduino board through the I2C bus. I am able to read the data from both sensors individually, but I can't read from both sensors if both are connected to the I2C bus.</p>
  
  <p>I can read the value from a single sensor while both are connected. When I try to find the address of both sensors using an I2C scanner, I can only find one sensor's address, which is the default 0x29. Individually I can read the address of the sensor but both have the same address. Does anybody know how to solve the issue?</p>
  
  <p>The I2C scanner code:</p>
  
  <pre><code>#include &lt;Wire.h&gt;
  #include &lt;Arduino.h&gt;
  
  // 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("&lt;delay="));
        Serial.println(delayFlag ? F("5&gt;") : F("0&gt;"));
        break;
      case 'e':
        // eeprom test TODO
        break;
      case 'h':
        header = !header;
        Serial.print(F("&lt;header="));
        Serial.println(header ? F("yes&gt;") : F("no&gt;"));
        break;
      case '?':
        state = HELP;
        break;
      case 'p':
        printAll = !printAll;
        Serial.print(F("&lt;print="));
        Serial.println(printAll ? F("all&gt;") : F("found&gt;"));
        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 &lt; speeds; s++) {
        Serial.print(F("\t"));
        Serial.print(speed[s]);
      }
      Serial.println(F("\t[KHz]"));
      for (uint8_t s = 0; s &lt; 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 &lt; 120; address++) {
      bool printLine = printAll;
      bool found[speeds];
      bool fnd = false;
      for (uint8_t s = 0; s &lt; 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 &amp;&amp; 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 &lt; 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."));
    }
  }
  </code></pre>
  
  <p>Code to read data from both sensors:</p>
  
  <pre><code>#include &lt;Wire.h&gt;
  #include &lt;SparkFun_VL6180X.h&gt;
  
  #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(&amp;identification1); // Retrieve manufacturer info from device memory
    printIdentification(&amp;identification1);
    sensor2.getIdentification(&amp;identification2); // Retrieve manufacturerinfo from device memory
    printIdentification(&amp;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-&gt;idModel);
    Serial.print("Model Rev = ");
    Serial.print(temp-&gt;idModelRevMajor);
    Serial.print(".");
    Serial.println(temp-&gt;idModelRevMinor);
    Serial.print("Module Rev = ");
    Serial.print(temp-&gt;idModuleRevMajor);
    Serial.print(".");
    Serial.println(temp-&gt;idModuleRevMinor);
    Serial.print("Manufacture Date = ");
    Serial.print((temp-&gt;idDate &gt;&gt; 3) &amp; 0x001F);
    Serial.print("/");
    Serial.print((temp-&gt;idDate &gt;&gt; 8) &amp; 0x000F);
    Serial.print("/1");
    Serial.print((temp-&gt;idDate &gt;&gt; 12) &amp; 0x000F);
    Serial.print(" Phase: ");
    Serial.println(temp-&gt;idDate &amp; 0x0007);
    Serial.print("Manufacture Time (s)= ");
    Serial.println(temp-&gt;idTime * 2);
    Serial.println();
    Serial.println();
  }
  </code></pre>