Need help with manual I2C communication to TOF Sensor VL6180 / TOF050C

Hey guys,
i am very new to the I2C communication topic and might need some help please!

I have a time of flight (TOF) sensor (TOF050C) and got it running with the Adafruit_VL6180X library. Unfortunately I cant use this library with my bigger project (it makes my screen flicker and it doesn't work properly). So I need to manually get the information from the sensor with the Wire.beginTransmission() command.
I tried to read the library's code for reference but its very confusing to me.

The things I figured out:

The sensors adress is: 0x29
Found the document for the sensor: https://download.kamami.pl/p587518-vl6180.pdf
Reading the value I need (distance measurement): 0x062 (not sure!)

So my code should look something like this(?)

void getNewRange(){
   Wire.beginTransmission(0x29);
   Wire.write(0x062);
   Wire.endTransmission()

   Wire.requestFrom(sensorAddress, 2); 

   if (Wire.available() == 2) {
      uint8_t highByte = Wire.read();
      uint8_t lowByte = Wire.read();
      uint16_t data = (highByte << 8) | lowByte;
      Serial.println(data);
}
};

But this doesnt really work :frowning:
Maybe someone can help me?
Thank you very much!

The Adafruit library uses normal code. They put effort in it and they tested it and made sure it works. Here is the source code: https://github.com/adafruit/Adafruit_VL6180X/blob/master/Adafruit_VL6180X.cpp

I would like to fix the problem.
Why is wrong with your screen ? Can you show the sketch ?

Thank you for your reply; here is my full code.
If I run the getRange() together with the drawDisplay() function in the same loop. The drawDisplay() doesnt work any more and the display starts to flicker and the ESP32 crashes. getRange() and drawDisplay() only work if they are executed by their own but not together! So my best solution is to write my own function to get the information from the TOF sensor...

#include <SPI.h>
#include <TFT_eSPI.h>
#include "images.h"
#include <Wire.h>
#include "Adafruit_VL6180X.h"

TFT_eSPI tft = TFT_eSPI();
TFT_eSprite spr = TFT_eSprite(&tft);
TFT_eSprite spr2 = TFT_eSprite(&tft);
Adafruit_VL6180X vl = Adafruit_VL6180X();

// EXTRA INTEGERS
int screenSize = 240;
int gradientX = 0;
int gradientY = 10;
int sprHeight = 28;
int sprWidth = 184;
int spr2Width = 80;

// just for a loop animation on the display
int x = 0;
int y = 0;
bool growing = true;
int step = 2;
int w = 0;

// just for a loop animation on the display
bool winkelGrow = true;
int pfeilX = 0;
int pfeilStep = 2;

// just some extra lines to draw on display
int crclMid = 129.5;
int lineX1 = crclMid + 41;  // dont change!!
int lineY1 = crclMid + 41;  // dont change!!
int lineX2 = crclMid + 60;
int lineY2 = crclMid + 60;

// define variables for TOF sensor
const int sensorAddress = 0x29;
#define RESULT__RANGE_VAL 0x062
int range = 0;

// extra colors for display
#define F_N 0x2dc3    // Green
#define F_D 0x0340    // Dark Green
#define F_L 0x5feb    // Light Green
#define WHITE 0xffff  // White

void setup(void) {
  Wire.begin();
  Serial.begin(115200);
  while (!Serial) {
    delay(1);
  }
  tft.init();
  // draw background and green circle
  tft.fillScreen(F_N);
  tft.fillCircle(screenSize / 2, screenSize / 2, 110, TFT_BLACK);

  // draw text with bitmap and other images
  tft.drawBitmap(0, 0, bgImg, 240, 240, WHITE);
  tft.drawBitmap(129.5, 129.5, bullsEye, 82, 82, WHITE);

  // create 2 sprite's
  spr.createSprite(sprWidth, sprHeight);
  spr2.createSprite(spr2Width, 32);
}

void loop() {
  //getRange();
  //testCommunication();
  //newGetRange();
  drawDisplay();
  delay(40);
};

// not finished coding!
void newGetRange(){
  Wire.beginTransmission(sensorAddress);
  Wire.write()
  Wire.endTransmission();

  Wire.requestFrom(sensorAddress, 2);

  if(Wire.available()<=2){
    
  }
}

// doesnt give correct output i want
void testCommunication() {
  Wire.beginTransmission(sensorAddress);
  Wire.write(0x062);  // Registeradresse, von der gelesen werden soll
  Wire.endTransmission();

  Wire.requestFrom(sensorAddress, 2); // Anfordern von 2 Bytes

  if (Wire.available() == 2) {
    uint8_t highByte = Wire.read();
    uint8_t lowByte = Wire.read();
    uint16_t data = (highByte << 8) | lowByte;
    
    Serial.print("Gelesene Daten: ");
    Serial.println(data);
  } else {
    Serial.println("Fehler beim Lesen der Daten");
  }
  
  //delay(1000); // Warte 1 Sekunde bis zur nächsten AbfrageF
}

//MAKES THE DISPLAY FLICKER AND CRASH ESP32!!!
void getRange() {
  range = vl.readRange();
  Serial.println(range);
}

// draws display
void drawDisplay() {
  // clear the sprite
  spr.fillSprite(TFT_BLACK);
  spr2.fillSprite(TFT_BLACK);

  if (growing) {
    w += step;
    if (w >= sprWidth - 4) {
      growing = false;
    }
  } else {
    w -= step;
    if (w <= 0) {
      growing = true;
    }
  }

  if (winkelGrow) {
    pfeilX += pfeilStep;
    if (pfeilX >= spr2Width - 12) {
      winkelGrow = false;
    }
  } else {
    pfeilX -= pfeilStep;
    if (pfeilX <= 0) {
      winkelGrow = true;
    }
  }

  spr.fillRoundRect(0, 0, sprWidth, sprHeight, sprHeight / 2, WHITE);
  spr.fillRoundRect(3, 3, sprWidth - 6, sprHeight - 6, (sprHeight - 6) / 2, TFT_BLACK);
  if (w >= 170) {
    spr.fillRoundRect(x + 3, y + 3, w - 3, sprHeight - 6, (sprHeight - 4) / 2, TFT_RED);
  } else {
    spr.fillRoundRect(x + 3, y + 3, w - 3, sprHeight - 6, (sprHeight - 4) / 2, F_N);
  }

  // extra Linie fuer indicator
  tft.drawLine(lineX1, lineY1, lineX2, lineY2, WHITE);
  tft.drawLine(lineX1 + 1, lineY1, lineX2 + 1, lineY2, WHITE);
  tft.drawLine(lineX1 - 1, lineY1, lineX2 - 1, lineY2, WHITE);
  tft.drawLine(lineX1, lineY1 + 1, lineX2, lineY2 + 1, WHITE);
  tft.drawLine(lineX1, lineY1 - 1, lineX2, lineY2 - 1, WHITE);

  spr2.drawBitmap(pfeilX, 0, pfeile, 12, 36, WHITE);
  spr2.fillRoundRect(0, 10, 25, 12, 0, 63488);
  spr2.fillRoundRect(25, 10, 30, 12, 0, 63488);
  spr2.fillRoundRect(25 + 30, 10, 25, 12, 0, F_N);

  spr.pushSprite(28, 95);
  spr2.pushSprite(43, 159);
}

Where does the display gets it power from ?
Do you have a multimeter to check the voltages ?

int can't hold decimal places!

The display and the sensor work with the 3.3v output from the esp32

Maybe there is a misunderstanding. The display is bugging and doesnt execute the drawDisplay() function. The stuff from the setup() is still being drawn on the display.
So power consumption is not the problem. Just the combination of these 2 librarys are a problem somehow.

I just need to know how to communicate with the i2c protocol but I need some help to get it to work.

Ok, thank you. But this is not my problem right now.

Is it? Why have you concluded that?

Please post the code that uses the ToF sensor library and has the flickering problem.

I think that the display uses the hardware SPI bus and the sensor uses the hardware I2C bus of the ESP32. In theory that should be no problem.
The Adafruit library makes use of the " Adafruit Bus IO Library" which is also for the SPI bus. As far as I can tell, it does not interfere with the SPI bus. You could try another library for the VL6180 to be sure.
Writing your own code is not easy. It is not just two Wire.read() to get the data. The sensor is much more complex than that.

The sensor and the display should have no influence on each other. That means that there is a bug or someone made a mistake.

1 Like
void getRange() {
  range = vl.readRange();
  Serial.println(range);
}

This code is using the library and makes my esp32 crash.

The following code communicates with the sensor via i2c protocol but its not giving me the right values. So my conclusion is, the manual approach is working but I need help to get the right values.

void testCommunication() {
  Wire.beginTransmission(0x29); // sensors address is 0x29 on i2c protocol
  Wire.write(0x062);  // Register address to get data from
  Wire.endTransmission();

  Wire.requestFrom(sensorAddress, 2);  // Get 2 bytes

  if (Wire.available() == 2) {
    uint8_t highByte = Wire.read();
    uint8_t lowByte = Wire.read();
    uint16_t data = (highByte << 8) | lowByte;

    Serial.print("Read data: ");
    Serial.println(data);
  } else {
    Serial.println("Error with loading data");
  }

  delay(1000); // wait 1 sec
}

The output is very random:

16:34:19.901 -> Gelesene Daten: 0

16:34:19.947 -> Gelesene Daten: 0

16:34:19.993 -> Gelesene Daten: 0

16:34:20.039 -> Gelesene Daten: 0

16:34:20.085 -> Gelesene Daten: 0

16:34:20.131 -> Gelesene Daten: 0

16:34:20.178 -> Gelesene Daten: 0

16:34:20.224 -> Gelesene Daten: 0

16:34:20.271 -> Gelesene Daten: 0

16:34:20.317 -> Gelesene Daten: 0

16:34:20.364 -> Gelesene Daten: 0

16:34:20.410 -> Gelesene Daten: 16128

16:34:20.456 -> Gelesene Daten: 0

16:34:20.502 -> Gelesene Daten: 1

16:34:20.548 -> Gelesene Daten: 307

16:34:20.594 -> Gelesene Daten: 13056

Sorry its german: "Gelesene Daten" => "data read"

@user_nick This is not going well. I don't see how this can result in a working project.

We see problems everywhere we look:

  1. The readRange() has waiting loops: https://github.com/adafruit/Adafruit_VL6180X/blob/master/Adafruit_VL6180X.cpp#L187
    I don't have a VL6180 sensor, so I can not test those waiting loops.
  2. I'm still not convinced that there is no power problem.
  3. When using a certain function of a combination of two pieces of code suddenly causes problems, then that is an indication that there could be a problem with memory or the stack. We would have to check your whole sketch, line by line.
  4. We can not give code to get data out of the sensor. It does not work that way. Have you seen the source code of the Adafruit library with all the initialization ?
  5. When the data of a byte is shifted 8 times to the left, then (in theory) nothing is left.
uint8_t highByte;
(highByte << 8)

This list can go on.

I still think that using a working library is your best option. Maybe you encountered a bug. But it is more likely a power or a memory problem.

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