I2C sensors disabling SERCOM3

I use an Arduino MKR ZERO and have set up 3 VL53L1X from Pololu via the default I2C pins and Pins D3, D4, and D5. I also set up a BT receiver via UART Serial2 using Pins D0 and D1 (SERCOM3) as per instructions from Arduino (https://docs.arduino.cc/tutorials/communication/SamdSercom).

They both worked great, when using separately. But when used together, the 3 VL53L1X still worked fine but they seemed to disable Serial2. In theory, both operations should be independent?

Can anyone offer some suggestions?
Thank you so much.

I'm not sure, it depends on which board is selected.
There are "arduino-zero", "arduino-mzero", "mkrzero" variants.
I think the MKR Zero is "mkrzero", and the Arduino M0 (designed in Italy) is "arduino-mzero".

This one seems to use SERCOM3 for the I2C bus: https://github.com/arduino/ArduinoCore-samd/blob/master/variants/arduino_zero/variant.cpp

This one seems to use SERCOM2 for the I2C bus: https://github.com/arduino/ArduinoCore-samd/blob/master/variants/mkrzero/variant.cpp

It should be independent, but there could be a bug.

@Koepel, thanks for the reply.
I am using a mkrzero so I purposedly chose "SERCOM3" and Pins D0 and D1 to avoid SERCOM2 which is being supposedly used by I2C Bus.

I think you did it right. Could you show a sketch that someone with a MKR Zero can test ?

@Koepel
Thank you for your help and interest in this issue.

As a newbie, the system did not let me embed my screen captures of the Outputs of my sketch when it was running. So below is the complete program listing whereas the code sections pertaining to my three I2C sensors are commented out, and you would be able to see that "Serial2 is available" when the sketch is running.

But when I enable my I2C codes, I can get my sensors data streaming in through the I2C port OK, but then "Serial2 is NOT AVAILABLE" anymore.

////// Code listing ////

/* CANNOT USE Serial2 and I2C sensors at the same time
 ********************************************************************************/

#include <Arduino.h>                              
#include <wiring_private.h>

// Serial2 pin and pad definitions 
#define PIN_SERIAL2_TX       (0ul)                // Pin description number for PIO_SERCOM on D0
#define PIN_SERIAL2_RX       (1ul)                // Pin description number for PIO_SERCOM on D1
#define PAD_SERIAL2_TX       (UART_TX_PAD_0)      // SERCOM pad 0 TX
#define PAD_SERIAL2_RX       (SERCOM_RX_PAD_1)    // SERCOM pad 1 RX
// Instantiate the Uart class named Serial2
Uart Serial2(&sercom3, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX);  // using SERCOM3

/*
// Setting up ToF sensors
#include <Wire.h>
#include <VL53L1X.h>   // Pololu Library
// The number of ToF sensors used on the robot
const uint8_t sensorCount = 3;  // 3 ToFs are used
int sensorRead = 0;  // via Keyboard Input with Serial.read() 
// The Arduino digital pin connected to the XSHUT pin of each sensor.
const uint8_t xshutPins[sensorCount] = { 3, 4, 5 };  // Digital Ports 3/4/5 used on MKR ZERO
VL53L1X sensors[sensorCount];  // instantiate Sensor Objects
int L_ToF = 0;
int C_ToF = 0;
int R_ToF = 0;
*/

/******END OF GLOBAL SETTINGS  ***************************/

void setup()
{
  Serial.begin(115200);
  delay(2000);  // wait for user to start Serial Monitor
  
  Serial2.begin(57600);          // Begin Serial2 connecting to BT-210/410
  pinPeripheral(0, PIO_SERCOM);   // Assign pins 0 (TX) & 1 (RX) with SERCOM functionality
  pinPeripheral(1, PIO_SERCOM);   // BT-210/410 TX Pin >> MKR D1 Pin (RX); BT-410 RX Pin >> MKR D0 Pin (TX)
  
/*
// Setting up ToF sensors
  Wire.begin();
  Wire.setClock(400000); // use 400 kHz I2C

  // Disable/reset all sensors by driving their XSHUT pins low.
  for (uint8_t i = 0; i < sensorCount; i++)
  {
    pinMode(xshutPins[i], OUTPUT);
    digitalWrite(xshutPins[i], LOW);
  }

  // Enable, initialize, and start each sensor, one by one.
  for (uint8_t i = 0; i < sensorCount; i++)
  {
    // Stop driving this sensor's XSHUT low. This should allow the carrier
    // board to pull it high. (We do NOT want to drive XSHUT high since it is
    // NOT LEVEL SHIFTED). Then wait 10 ms for the sensor to start up.
    pinMode(xshutPins[i], INPUT);
    delay(10);  // wait for sensor to start up

    sensors[i].setTimeout(500);
    if (!sensors[i].init())
    {
      Serial.print("Failed to detect and initialize sensor ");
      Serial.println(i);
      while (1);
    }

    // Each sensor must have its address changed to a unique value other than
    // the default of 0x29 (except for the last one, which could be left at
    // the default). To make it simple, we'll just count up from 0x2A (i.e. 2A, 2B, 2C).
    sensors[i].setAddress(0x2A + i);

    sensors[i].startContinuous(15);   // default=50 ms, 15 is about lowest value used without TIMEOUT error
    Serial.print(" Timing Budget (us) = \t");
    Serial.println(sensors[i].getMeasurementTimingBudget());  // showing default value of 50000 us or 50 ms    
  }    // end of Init ToFs
*/
}   // end of setup()

void loop()
{
/*
  L_ToF = sensors[0].read();  // in mm
  C_ToF = sensors[1].read();
  R_ToF = sensors[2].read();
  Serial.println(String(L_ToF) + "\t" + String(C_ToF) + "\t" + String(R_ToF));
*/
 
  if(Serial2.available())  
  {
    Serial.println("Serial 2 is available!");
  }
  else 
  {
    Serial.println("Serial 2 is NOT available!");
  }
 
}  // end of loop()

void SERCOM3_Handler()    // Interrupt handler for SERCOM3
{
  Serial2.IrqHandler();
}

Regards.

@Koepel

I did some more experiments, and this is what I found:

  1. I used a single VL53L1X sensor and hooked it up via the usual I2C Pins (D11 and D12) and I had the same problem of having Serial2 being disabled by the use of this I2C sensor.

  2. I also have a single CL53L5CX that I hooked up to that miniature JST 5-pin connector near the microUSB port (see picture below).

and interestingly, this setup allowed this I2C sensor and Serial2 to work together. From my limited knowledge, doesn't this JST connector represent the same I2C pins as D11 and D12?

Thanks.

Hi @roboteer22

Are you powering your Pololu VL53L1X boards with a +5V or 3.3V supply?

Looking at the Pololu schematic for this board, they include I2C level shifters, however the external SCL and SDA lines are pulled up to the V(in) supply voltage.

This means that for the MKRZero, these boards must be powered only with 3.3V, (since the MKRZero's SAMD21 microcontroller is a 3.3V device).

Hello @MartinL,

The web info at Pololu (Pololu - VL53L1X Time-of-Flight Distance Sensor Carrier with Voltage Regulator, 400cm Max) mentions that the board includes a 2.8 V linear regulator and level-shifters that allow it to work over an input voltage range of 2.6 V to 5.5 V, so I had been connecting 5V from the MKR ZERO to the VIN pin of this sensor. But your suggestion of 3.3 V is a good idea though, so I just tried it out (i.e., connecting VCC 3.3V on the MKR ZERO to the VIN pin of the sensor). But the same problem remains, i.e., using the I2C sensor will disable Serial2 which is a UART.

I'll probably have to shift to using a BLE SPI module instead like this one from AdaFruit (Adafruit Bluefruit LE SPI Friend - Bluetooth Low Energy (BLE) : ID 2633 : $17.50 : Adafruit Industries, Unique & fun DIY electronics and kits).

Thanks.

@roboteer22 Looking at the VL531X datasheet is says that it uses I2C address: 0x52. You mention that you're using 3 devices.

I was just wondering how you're addressing the additional devices on the same I2C port?

They are 100% exactly the same.
The power pin of the JST connector is a 5V pin, and the SDA and SCL are 3.3V level signals.
Is this a hardware problem ? Can you measure with the multimeter that those pins are connected ? Is there something wrong with powering the modules or with the GND ? Do you connect a battery and it stops working with the battery connected ?

The VIN pin of the MKR Zero is only for 5V power input and nothing else. If you applied 12V there in the past then the board is broken.
Serial and Bluetooth modules have often 3.3V signals, even if they are powered with 5V.

Hi @roboteer22

It seems like the VL53L1X devices use a peculiar mutliple device strategy that involves releasing the shutdown pin and setting each device's I2C address in turn.

@Koepel , @MartinL

Thanks for offering different troubleshooting ideas, that helps me look for more work-around ideas and I think that I have found the "problem", although not the "solution" yet.

As I have used successfully the CL53L5CX on the mini JST connector, I just moved it to the regular I2C pins (D11 and D12) and both CL535CX and Serial2 now WORK TOGETHER, as expected!

I bought both CL53L5CX and CL53L1X sensors from Pololu, but it looks like that the Pololu's sample software for the CL53L1X is using I2C somewhat differently than the sample software for the CL53L5CX. So at least, I now know that I need to direct my questions to Pololu folks instead!

Thank you very much for your help!

But we have only just started :stuck_out_tongue_winking_eye:

Please edit your post and fix the component names, give links to the libraries that you use and show your sketch.

Pololu VL53L5CX : https://www.pololu.com/product/3417
They point to the Sparkfun library: https://github.com/sparkfun/SparkFun_VL53L5CX_Arduino_Library
It seems a normal library, that accepts a TwoWire pointer for the I2C bus which is set default to the "Wire" object here.

Pololu VL53L1X : https://www.pololu.com/product/3415
They have a simplified library: https://github.com/pololu/vl53l1x-arduino
And a implementation of the driver code as supplied by ST: https://github.com/pololu/vl53l1x-st-api-arduino
The simplified library uses a pointer to a TwoWire object as well and default the "Wire" object is used here.

I can not find anything weird or something with SERCOM or Serial2 in those libraries. At this moment I'm thinking of a bug in the sketch :thinking:
You could combine Serial2 with a I2C Scanner sketch, then you know that the hardware and the Arduino board are working.

@Koepel @MartinL
Thank you very much for your persistent help!

But I had found a work around using that Adafruit BLE SPI module that I mentioned earlier.

In short, the Pololu's way of reading the ToF sensors somehow blocks the SERCOM services, but NOT the SPI services. How exactly, I don't know much about Arduino OS to even guess. But I am very glad to have found a work-around so that I can move on with my project.

For more details, please see my Pololu post at https://forum.pololu.com/t/vl53l1x-disabling-serial-port-on-arduino-mkr-zero/23158/5

Regards.

Thanks for the link.
I'm glad you found a way around it, but it is very annoying that we don't know what causes it :face_with_spiral_eyes:

Thanks to a tip from Patrick of Pololu, I have figured out a second solution that uses this sensor in a non-blocking way. See picture below:

Basically, check first if new data is ready with Line 85, then do a non-blocking read(false) with Line 87. This "unblocked" Serial2 also.

For reasons still unknown to me, using read() in blocking mode (Line 89) somehow made Serial2 (created via SERCOM) "unavailable" in the remainder of my sketch. But if I use the BLE SPI module, with the first solution shown above, I can read these sensors in "blocking" mode! :face_with_spiral_eyes:

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