Code only Reads two Sensors once and gives an Error After

Hello would love some help with understanding what's going on in my code and a fix for it.

I am trying to use 2x time of flight sensors (VL53L4CD) using the stm32duino/VL53L4CD library.

My code currently gets the reading once but then gives me the following error: [ 2883][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1

This is what I have written so far.

/* Includes ------------------------------------------------------------------*/
#include <Arduino.h>
#include <Wire.h>
#include <vl53l4cd_class.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <WiFi.h>
//#include <ESPAsyncWebServer.h>

#define DEV_I2C Wire
#define SerialPort Serial
char report[64];

// address we will assign if dual sensor is present
#define sensor1add 0x30
#define sensor2add 0x31

// set the pins to shutdown
#define xshut1 A0
#define xshut2 A1
#define GFX_BL DF_GFX_BL

//this holds the measurement
VL53L4CD_Result_t results1;
VL53L4CD_Result_t results2;
float sensor1, sensor2;

// Components.
VL53L4CD sensor1_vl53l4cd_sat(&DEV_I2C, A0);
VL53L4CD sensor2_vl53l4cd_sat(&DEV_I2C, A1);

//init Wifi
/*void initWifi(){
    Serial.print("Setting AP (Access Point)...");
  // No password
  WiFi.softAP (ssid);
  // Start WiFi Access Point
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.print(IP);
    // Print ESP8266 Local IP Adress
  Serial.println(WiFi.localIP());
}*/

//init sensors
void initSensor(VL53L4CD sensorX)
{
  // Init sensor1
  // Configure VL53L4CD satellite component.
  sensorX.begin();
  // Switch off VL53L4CD satellite component.
  sensorX.VL53L4CD_Off();
  //Initialize VL53L4CD satellite component.
  sensorX.InitSensor();
  // Program the highest possible TimingBudget, without enabling the
  // low power mode. This should give the best accuracy
  sensorX.VL53L4CD_SetRangeTiming(200, 0);
  sensorX.VL53L4CD_SetOffset(-10);
  // Start Measurements
  sensorX.VL53L4CD_StartRanging();
}

//getSensor1Reading
void getSensor1Reading(uint8_t status, uint8_t NewDataReady)
{
  digitalWrite(xshut1, HIGH);
  if ((!status) && (NewDataReady != 0)) {
    // (Mandatory) Clear HW interrupt to restart measurements
    sensor1_vl53l4cd_sat.VL53L4CD_ClearInterrupt();
    // Read measured distance. RangeStatus = 0 means valid data
    sensor1_vl53l4cd_sat.VL53L4CD_GetResult(&results1);
    snprintf(report, sizeof(report), "Status = %3u, Distance = %5u mm, Signal = %6u kcps/spad\r\n",
             results1.range_status,
             results1.distance_mm,
             results1.signal_per_spad_kcps);
    sensor1 = results1.distance_mm;
    Serial.println((String)"This is Sensor1 " + (float)sensor1 + (String)"mm");
  }
  digitalWrite(xshut1, LOW);
}

//getSensor2Reading
void getSensor2Reading(uint8_t status, uint8_t NewDataReady)
{
  digitalWrite(xshut2, HIGH);
  if ((!status) && (NewDataReady != 0)) {
    // (Mandatory) Clear HW interrupt to restart measurements
    sensor2_vl53l4cd_sat.VL53L4CD_ClearInterrupt();
    // Read measured distance. RangeStatus = 0 means valid data
    sensor2_vl53l4cd_sat.VL53L4CD_GetResult(&results2);
    snprintf(report, sizeof(report), "Status = %3u, Distance = %5u mm, Signal = %6u kcps/spad\r\n",
             results2.range_status,
             results2.distance_mm,
             results2.signal_per_spad_kcps);
    sensor2 = results2.distance_mm;
    Serial.println((String)"This is Sensor2 " + (float)sensor2 + (String)"mm");
  }
  digitalWrite(xshut2, LOW);
}

/*void offset()
{

}*/

/* Setup ---------------------------------------------------------------------*/
void setup()
{
  // Initialize serial for output.
  SerialPort.begin(115200);
  SerialPort.println("Starting...");
  // Initialize I2C bus.
  DEV_I2C.begin();
  
  initSensor(sensor1_vl53l4cd_sat);
  initSensor(sensor2_vl53l4cd_sat);
}

void loop()
{
  uint8_t NewDataReady1 = 0;
  uint8_t NewDataReady2 = 0;
  uint8_t status1;
  uint8_t status2;
  do {
    status1 = sensor1_vl53l4cd_sat.VL53L4CD_CheckForDataReady(&NewDataReady1);
    status2 = sensor2_vl53l4cd_sat.VL53L4CD_CheckForDataReady(&NewDataReady2);
  } while (!NewDataReady1 || !NewDataReady2);
  getSensor1Reading(status1, NewDataReady1);
  getSensor2Reading(status2, NewDataReady2);
}

And this is what I am getting as an output

--- forcing DTR inactive
--- forcing RTS inactive
--- Terminal on COM9 | 115200 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, esp32_exception_decoder, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
This is Sensor1 0.00mm
This is Sensor2 30.00mm
[  2883][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1
[  3884][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error 263
[  3884][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1
[  3886][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1
[  3893][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1
[  3900][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1
[  3907][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1
[  3914][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1
[  3921][E][Wire.cpp:499] requestFrom(): i2cWriteReadNonStop returned Error -1

Thanks!

You have two sensors using the same I2C address on the same I2C bus. That won't work. It seems you cannot constantly change the I2C address of a sensor but you can change it for the session (until next power cycle) and you should do that at first.

Unfortunately your library supports that in a rather unusual way but at least it does. Supply the address to the InitSensor() method.
You should provide the sensor object to your initSensor routine by reference otherwise you do the initialization on a copy of it.

Good catch I had the addresses defined at the top but never set them and just used the xshut pins.

I did change them and turned them into "uint8_t"s and added that as an input for my initSensor method. However, when I pass it through the InitSensor(uint8_t) library method to set the address I seem to still get the same result. Also I tried to set the I2C address using the SetI2CAdress method, but also with the same result.

I also tried changing my digitalWrite(xshut,Low/High) to the VL53L4CD_Off() and VL53L4CD_On(), however that hasn't changed any results either.

Am I going down the path that you are thinking of?

//init sensors
void initSensor(VL53L4CD sensorX, uint8_t sensoradd)
{
  // Init sensor1
  //Set sensor address.
  sensorX.VL53L4CD_SetI2CAddress(sensoradd);
  // Configure VL53L4CD satellite component.
  sensorX.begin();
  // Switch off VL53L4CD satellite component.
  sensorX.VL53L4CD_Off();
  //Initialize VL53L4CD satellite component.
  sensorX.InitSensor();
  // Program the highest possible TimingBudget, without enabling the
  // low power mode. This should give the best accuracy
  sensorX.VL53L4CD_SetRangeTiming(200, 0);
  sensorX.VL53L4CD_SetOffset(-10);
  // Start Measurements
  sensorX.VL53L4CD_StartRanging();
}

//getSensor1Reading
void getSensor1Reading(uint8_t status, uint8_t NewDataReady)
{
  sensor1_vl53l4cd_sat.VL53L4CD_On();
  if ((!status) && (NewDataReady != 0)) {
    // (Mandatory) Clear HW interrupt to restart measurements
    sensor1_vl53l4cd_sat.VL53L4CD_ClearInterrupt();
    // Read measured distance. RangeStatus = 0 means valid data
    sensor1_vl53l4cd_sat.VL53L4CD_GetResult(&results1);
    snprintf(report, sizeof(report), "Status = %3u, Distance = %5u mm, Signal = %6u kcps/spad\r\n",
             results1.range_status,
             results1.distance_mm,
             results1.signal_per_spad_kcps);
    sensor1 = results1.distance_mm;
    Serial.println((String)"This is Sensor1 " + (float)sensor1 + (String)"mm");
  }
  sensor1_vl53l4cd_sat.VL53L4CD_Off();
}

//getSensor2Reading
void getSensor2Reading(uint8_t status, uint8_t NewDataReady)
{
  sensor2_vl53l4cd_sat.VL53L4CD_On();
  Serial.println("Sensor 2 is on");
  if ((!status) && (NewDataReady != 0)) {
    // (Mandatory) Clear HW interrupt to restart measurements
    sensor2_vl53l4cd_sat.VL53L4CD_ClearInterrupt();
    // Read measured distance. RangeStatus = 0 means valid data
    sensor2_vl53l4cd_sat.VL53L4CD_GetResult(&results2);
    snprintf(report, sizeof(report), "Status = %3u, Distance = %5u mm, Signal = %6u kcps/spad\r\n",
             results2.range_status,
             results2.distance_mm,
             results2.signal_per_spad_kcps);
    sensor2 = results2.distance_mm;
    Serial.println((String)"This is Sensor2 " + (float)sensor2 + (String)"mm");
  }
  sensor2_vl53l4cd_sat.VL53L4CD_Off();
}

You initSensor() routine still operates on a copy instead as on the original instance. Provide that parameter by reference!

Thanks pylon! I actually found the issue to be with my addresses, it seemed to not like having the addresses of 0x29 and 0x28. I changed the addresses to be 2 apart and that seems to have resolved the issue.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.