Problem:
I'm working on a project with a custom Arduino SAMD21 board where I need to read data from a VL53L5CX sensor. The I2C communication works perfectly in the setup() function, but when I try to initialize and communicate with the sensor within a FreeRTOS task, it fails to find the sensor. Which makes clear that it can't be a hardware problem.
Details:
Board: Custom Arduino SAMD21
Sensor: VL53L5CX (connected via I2C)
Library: Using SparkFun's VL53L5CX library
OS: FreeRTOS
Symptoms:
The sensor initializes and communicates correctly in the setup() function, and the device ID is successfully read. Within the FreeRTOS task (sensorThreadFunc), the sensor is not detected, and I2C communication fails.
Code Snippets:
Working Code in setup():
void setup() {
SERIALLL.begin(115200);
delay(7000); // Prevents USB driver crash on startup
while (!Serial);
SERIALLL.println("Program start");
Wire.begin(); // Reset I2C bus to 100kHz
Wire.setClock(1000000); // Set I2C freq to 1MHz
// Check I2C communication
Wire.beginTransmission(0x29);
if (Wire.endTransmission() == 0) {
SERIALLL.println("Sensor found at address 0x29");
// Optionally, read a specific register (for example, the device ID register)
byte registerAddress = 0x7F; // Example register address
Wire.beginTransmission(0x29);
Wire.write(registerAddress);
Wire.endTransmission();
Wire.requestFrom(0x29, (byte)1);
if (Wire.available()) {
byte data = Wire.read();
SERIALLL.print("Register 0x");
SERIALLL.print(registerAddress, HEX);
SERIALLL.print(" = 0x");
SERIALLL.println(data, HEX);
} else {
SERIALLL.println("Failed to read from register.");
}
} else {
SERIALLL.println("Sensor not found");
}
}
Failing Code in FreeRTOS Task:
void sensorThreadFunc(void *pvParameters) {
(void)pvParameters;
xSemaphoreTake(semSerial, portMAX_DELAY);
SERIALLL.println("Sensor-Thread Active!");
xSemaphoreGive(semSerial);
Wire.begin();
Wire.setClock(1000000);
xSemaphoreTake(semSerial, portMAX_DELAY);
SERIALLL.println("Scanning for I2C devices...");
for (byte address = 1; address < 127; address++) {
Wire.beginTransmission(address);
if (Wire.endTransmission() == 0) {
SERIALLL.print("I2C device found at address 0x");
SERIALLL.println(address, HEX);
}
}
xSemaphoreGive(semSerial);
if (!VL53L5CX.begin()) {
xSemaphoreTake(semSerial, portMAX_DELAY);
SERIALLL.println("Sensor not found - Task deleted.");
xSemaphoreGive(semSerial);
vTaskDelete(NULL);
}
SERIALLL.println("Sensor initialized");
for (;;) {
// Sensor data reading and processing
}
}
Output:
Register 0x7F = 0x0
Sensor-Thread Active!
Scanning for I2C devices...
I2C scan completed.
Checking for I2C device at address 0x29
No I2C device found at address 0x29
Troubleshooting Steps Tried:
Added delays before sensor initialization in the task.
Re-initialized the I2C bus within the task.
Checked for proper semaphore usage to avoid conflicts.
Verified hardware connections.
Additional Information:
I have programmed the same code on a regular Arduino Zero, and it works without any issues. My suspicion is that the problem might be related to using the internal quartz oscillator on the SAMD21, because I didn't implement one in my custom board.
Request:
Has anyone encountered a similar issue or can provide insight into why I2C communication fails within a FreeRTOS task but works in setup()? Any suggestions for resolving this would be greatly appreciated.