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".
@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.
@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();
}
I did some more experiments, and this is what I found:
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.
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?
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).
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.
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.
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.
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!
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
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.
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!