Two VL53L1X - Hardware NACK Detected

I have 2 VL53L1X connected on an esp32 with 2 vibration motors.

#include <Wire.h>
#include "WiFi.h"
#include <VL53L1X.h>

// I2C pins
#define SDA_PIN 21
#define SCL_PIN 22

// XSHUT pins
#define XSHUT_LEFT 4
#define XSHUT_RIGHT 16

// Motor pins
#define MOTOR_LEFT 26
#define MOTOR_RIGHT 33

// I2C addresses
#define ADDR_LEFT 0x30
#define ADDR_RIGHT 0x31

// Thresholds
#define DISTANCE_THRESHOLD 1350       // in mm (1.2 meters)
#define VIBRATION_DURATION 1000       // 1 sec
#define MAX_PRESENCE_DURATION 5000    // 5 sec

VL53L1X sensorLeft;
VL53L1X sensorRight;

// State tracking
unsigned long lastTriggerLeft = 0;
unsigned long lastTriggerRight = 0;
unsigned long presenceStartLeft = 0;
unsigned long presenceStartRight = 0;
bool leftInZone = false;
bool rightInZone = false;
bool leftAlreadyTriggered = false;
bool rightAlreadyTriggered = false;

// Check if sensor reading is valid and in range
bool isValidReading(VL53L1X &sensor, uint16_t threshold, String direction) {
  sensor.read();
  Serial.print(direction);
  Serial.print(": ");
  Serial.print(sensor.ranging_data.range_mm);
  Serial.print("mm");
  return (sensor.ranging_data.range_status == 0 &&
          sensor.ranging_data.range_mm < threshold);
}

void setup() {
  delay(500);
  Serial.begin(115200);
  

  // Disable Wi-Fi
  WiFi.disconnect(true);  // Disconnect and erase Wi-Fi credentials
  WiFi.mode(WIFI_OFF);    // Turn off Wi-Fi
          // Stop the Wi-Fi driver

  // Disable Bluetooth
  // esp_bt_controller_disable();  // Disable BT controller
  // esp_bt_controller_deinit();  // Deinitialize BT controller

  pinMode(MOTOR_LEFT, OUTPUT);
  pinMode(MOTOR_RIGHT, OUTPUT);
  digitalWrite(MOTOR_LEFT, LOW);
  digitalWrite(MOTOR_RIGHT, LOW);

  pinMode(XSHUT_LEFT, OUTPUT);
  pinMode(XSHUT_RIGHT, OUTPUT);

  digitalWrite(XSHUT_LEFT, LOW);
  digitalWrite(XSHUT_RIGHT, LOW);
  delay(10);

  Wire.begin(SDA_PIN, SCL_PIN, 100000);
  delay(10);

  // === Power and init LEFT sensor ===
  // digitalWrite(XSHUT_LEFT, HIGH);
  pinMode(XSHUT_LEFT, INPUT);
  delay(100);
  sensorLeft.setTimeout(500);
  if (!sensorLeft.init()) {
    Serial.println("Failed to init LEFT sensor");
    while (1);
  }
  sensorLeft.setAddress(ADDR_LEFT);
  Serial.println("Left sensor set to 0x30");

  // === Power and init RIGHT sensor ===
  // digitalWrite(XSHUT_RIGHT, HIGH);
  pinMode(XSHUT_RIGHT, INPUT);
  delay(100);
  sensorRight.setTimeout(500);
  if (!sensorRight.init()) {
    Serial.println("Failed to init RIGHT sensor");
    while (1);
  }
  Serial.println("Right sensor set to 0x29");
  

  sensorLeft.setDistanceMode(VL53L1X::Medium);
  sensorRight.setDistanceMode(VL53L1X::Medium);

  sensorLeft.setMeasurementTimingBudget(50000);
  sensorRight.setMeasurementTimingBudget(50000);

  sensorLeft.startContinuous(50);
  sensorRight.startContinuous(50);
}

void loop() {
  unsigned long now = millis();

  // ======= LEFT SENSOR =======
  bool leftDetected = isValidReading(sensorLeft, DISTANCE_THRESHOLD, "Left");

  if (leftDetected) {
    if (!leftInZone) {
      // First time detected
      presenceStartLeft = now;
      leftInZone = true;
      leftAlreadyTriggered = false;
    }

    if (!leftAlreadyTriggered && (now - presenceStartLeft < MAX_PRESENCE_DURATION)) {
      digitalWrite(MOTOR_LEFT, HIGH);
      lastTriggerLeft = now;
      leftAlreadyTriggered = true;
      Serial.print(" LEFT: TRIGGERED");
    }

    if (leftAlreadyTriggered && (now - lastTriggerLeft >= VIBRATION_DURATION)) {
      digitalWrite(MOTOR_LEFT, LOW);
      Serial.print(" LEFT: OFF");
    }

    if ((now - presenceStartLeft) >= MAX_PRESENCE_DURATION) {
      Serial.print(" LEFT: PRESENCE CAPPED");
    }

  } else {
    // No object in range
    leftInZone = false;
    leftAlreadyTriggered = false;
    presenceStartLeft = 0;
    digitalWrite(MOTOR_LEFT, LOW);
    Serial.print(" LEFT: CLEAR");
  }

  Serial.print("\t");

  // ======= RIGHT SENSOR =======
  bool rightDetected = isValidReading(sensorRight, DISTANCE_THRESHOLD, "Right");

  if (rightDetected) {
    if (!rightInZone) {
      presenceStartRight = now;
      rightInZone = true;
      rightAlreadyTriggered = false;
    }

    if (!rightAlreadyTriggered && (now - presenceStartRight < MAX_PRESENCE_DURATION)) {
      digitalWrite(MOTOR_RIGHT, HIGH);
      lastTriggerRight = now;
      rightAlreadyTriggered = true;
      Serial.print(" RIGHT: TRIGGERED");
    }

    if (rightAlreadyTriggered && (now - lastTriggerRight >= VIBRATION_DURATION)) {
      digitalWrite(MOTOR_RIGHT, LOW);
      Serial.print(" RIGHT: OFF");
    }

    if ((now - presenceStartRight) >= MAX_PRESENCE_DURATION) {
      Serial.print(" RIGHT: PRESENCE CAPPED");
    }

  } else {
    rightInZone = false;
    rightAlreadyTriggered = false;
    presenceStartRight = 0;
    digitalWrite(MOTOR_RIGHT, LOW);
    Serial.print(" RIGHT: CLEAR");
  }

  Serial.println();
  delay(50);
}

Im using 12 inches wires to connect them, checked continuity, sensor has built in pull up resistor.

Error:

E (9098) i2c.master: I2C transaction unexpected nack detected
E (9103) i2c.master: s_i2c_synchronous_transaction(945): I2C transaction failed
E (9110) i2c.master: i2c_master_receive(1261): I2C transaction failed
E (9116) i2c.master: I2C hardware NACK detected
E (9120) i2c.master: I2C transaction unexpected nack detected
E (9126) i2c.master: s_i2c_synchronous_transaction(945): I2C transaction failed
E (9133) i2c.master: i2c_master_multi_buffer_transmit(1207): I2C transaction failed
E (9140) i2c.master: I2C hardware NACK detected
E (9144) i2c.master: I2C transaction unexpected nack detected

What to do? Thanks

Hello.

I moved your post to the sensors support category since that seems like a better place for it.

Can you also try testing your sensors in a minimal setup using the example programs from our library with minimal modification? First, please try testing them one at a time and see if you can get them working that way before trying to use them together.

Can you also post some pictures that show all of your physical connections, including close-up pictures of both sides of your board?

- Patrick

It actually works when i only use 1 pair (1 vl43l1x and 1 vibration motor) without any problems at all (for both sensors), I am guessing that probably this is because of voltage issues? Or other?

It is probably too early to try and identify a specific cause. We need more information, but we can at least rule out any issues with the sensors themselves given your latest observation.

Can you provide more details about the overall setup as well as the pictures I asked for in my previous post? Are you able to use both sensors if you load the ContinuousMulipleSensors example program from our VL53L1X Arduino library with minimal modifications? (You will need to change sensorCount variable and the xshutPins array to match your setup.)

- Patrick

I will try to load the program without that much modifications and i will update, thank you.



I do not have other colored wires. But the yellow and green in the same row are the SDA(YELLOW, 21) and SCL(GREEN, 22). The two whites are for XSHUT (Pin 4 and 16).

The other row has two wire, yellow and white for the vibration motor which is sticked to the helmet.

I am not a good solderer, but i tested the continuity, it all works good.

Default code, just changed XSHUT pins:

This is the screenshot, it looks like it is not working? I tried commenting the Serial part to check if it is the issue:

Commented the !Serial Loop:

And now, it is still not working, back to the NACK error problem.

Was only able to get a glimpse:
image

None of the boards in your pictures look like our VL53L1X carriers (nor any other VL53L1X carriers I am familiar with). Can you post some close up close-up pictures of both sides of your sensor boards?

If you are not using our board, one immediate thing to check is if the XSHUT pins are pulled high by your board like they are in our design. If not, you should either add them or modify your code to use the ESP32’s internal pull-ups, i.e. replace line 43 from our example with:

pinMode(xshutPins[i], INPUT_PULLUP);

- Patrick