I2C problem with Wire.h for WiFi rev2

Hello everyone!

First time poster, I hope I don’t make any mistakes with the formatting. Anyway I just got into microcontroller programming for the university and I think I found a problem in the Wire.h library for Arduino WiFi rev2.

The problem
I am working with a VEML6040 sensor from Vishay which measures the luminosity for three different colours and white. The sensor responds to I2c scans and actually to almost all of my commands.
The problem is with reading from the sensor. If I send a stop condition after sending the read command, the sensor responds but always with the same colour independently of the colour command sent.
If I do it properly, with a reapeated start as required by the datasheet, the function Wire.requestFrom doens’t return any value and hangs.

The same code, with the repeated start, works properly for a ESP32 (HUZZAH32 Feather), returning proper values for each of the color.

The attempted solutions
I looked a lot into the library and into the ATmega4809 datasheet and the problem is: the library seems to do everything properly. The TWI0.MSTATUS register returns the proper value for OWNED after the use of the Wire.endTrasmission(false).
Moreover, by inserting returns I figured that the Wire.requestFrom function manages to set the TWI0.MADDR for reading but it never obtains an interrupt, remaining stuck in the while used to wait for it.

I cannot explain this behaviour since the ESP32 clearly registers an interrupt. Indeed, in that case it returns the proper values.

The code
Here is the code. As I said, the same identical code works properly for the ESP32.

#include <Wire.h>

const uint8_t VEML_CONF = 0x00;
const uint8_t VEML_ADDR = 0x10;
const uint8_t VEML_R = 0x08;
const uint8_t VEML_G = 0x09;
const uint8_t VEML_B = 0x0A;
const uint8_t VEML_W = 0x0B;

const uint8_t intTime = 0x06;  // 0 -> 40 ms: ++ -> x2 until 6;
const uint8_t mode = 0x03; // 0 -> Auto;   1 -> Force, no Trigger; -> 3 Force, Trigger; 


void setup() {
  Serial.begin(9600);
  Serial.println();
  Wire.setClock(100000);
  Wire.begin();;
  VEML_test();
  delay(2000);
}

void loop() {
  uint16_t red, blue, green, white;

  VEML_init();
  
  red = VEML_read(VEML_R);
  green = VEML_read(VEML_G);
  blue = VEML_read(VEML_B);
  white = VEML_read(VEML_W);
  
  Serial.println("VEML DATA");
  Serial.println();
  Serial.println();
  Serial.print("\tRed:\t");
  Serial.print(red);
  Serial.println();
  Serial.print("\tGreen:\t");
  Serial.print(green);
  Serial.println();
  Serial.print("\tBlue:\t");
  Serial.print(blue);
  Serial.println();
  Serial.print("\tWhite:\t");
  Serial.println(white);
  Serial.println();
  VEML_disable();
  delay(5000);

  
}


void VEML_init() {        //Sends the command to make a measurement. Works.
  uint8_t conf = 0x00;
  conf = (intTime << 4) | (mode << 1);
  conf &= 0xFE;
  VEML_write(VEML_CONF, conf);
}

void VEML_test() {        //Runs to ensure the device is properly connected. Works. 
  uint16_t test = 0;
  VEML_init();
  test = VEML_read(VEML_W);
  Serial.print(test);
  if (test) Serial.println("  >>  Sensor online.");
  Serial.println();
}

void VEML_disable() {     //Puts the device in "sleep mode". Seems to work. (Excluding it from
                          //the software doesn't solve the problem)
  uint8_t conf = (intTime << 4) | (0x03);
  
  VEML_write(VEML_CONF, conf);
  delay(100);
}


uint16_t VEML_read(uint8_t command) { //Reads the command. It doesn't work properly.
  
  uint16_t data = 0x0000;
  
  Wire.beginTransmission(VEML_ADDR);
  Wire.write(command);
  Wire.endTransmission(false);  //Here the function hangs. If set true, the function doesn't hang, but the
                                //value returned is always the same independently of the command.
  delay(10);
  
  delay(100);
  Wire.requestFrom(VEML_ADDR, 2, true);
  while (Wire.available()) {
    data = Wire.read();
    data |= Wire.read() << 8;
  }

  delay(200);  
  return data;
}

void VEML_write(uint8_t command, uint8_t settings) {  //Sends the command. It works.
  Wire.beginTransmission(VEML_ADDR);
  Wire.write(command); 
  Wire.write(settings); 
  Wire.write(0x00);
  Wire.endTransmission(true);
  delay(4000);
}

Conclusions
To me it seems that the Wire.h library has to have a problem handling the “combined transaction”, as the ATmega4809 puts it, when a repeated start is issued. I am very unknowledgeable and unexperienced in this matters so I’d beg you to help me identify and maybe solve the problem, so that other people can avoid spending days trying to figure out the system from scratch and maybe patch the library. Thank you.

Wish you a wonderful day,
Filippo

I assume that you use pullup resistors (the datasheet says use 2k2) connected to 3V3 ?

Your sensor is a 3V3 sensor. So is an ESP32. But the Arduino Uno WiFi Rev2 is a 5V device. The 3V3 signals from the sensor may be borderline for the Arduino. I use a (bidirectional) logic level shifter when connecting 3V3 sensors to my Uno WiFi Rev2.