My I2C bus communicates fine when I choose pretty much anything other than 100 or 200 kHz clock speeds. For example, 10, 50, 80, 90, 110, 400 kHz all work fine. When using 100 or 200 kHz, I get acknowledgements from the sensor, but the sensor data is corrupted.
This took me a little while to figure out so I thought I’d share the “work-around”. It’d also be great if someone could explain what’s going on.
Hardware setup:
Board: Artemis OpenLogIn
Arduino IDE “board” is: Redboard Artemis ATP (as specified by the Artemis OpenLog git repo)
Core/Apollo3 Library: 2.1.1
I2C Sensor: Lidar v4LED
Software:
#include <Wire.h>
#include "LIDARLite_v4LED.h"
// Artemis OLA pins.
const byte PIN_QWIIC_SCL = 8;
const byte PIN_QWIIC_SDA = 9;
const byte PIN_QWIIC_POWER = 18; // Qwiic bus power control.
// Set up a I2C using Wire.h.
TwoWire qwiic(PIN_QWIIC_SDA, PIN_QWIIC_SCL);
// Instantiate a lidar class.
const byte ADDR_LIDAR = 0x62;
LIDARLite_v4LED myLIDAR; // Click here to get the library: http://librarymanager/All#SparkFun_LIDARLitev4 by SparkFun
void setup() {
Serial.begin(115200);
// Setup the I2C bus.
Serial.println("Setup the I2C (qwiic) bus...");
pinMode(PIN_QWIIC_POWER, OUTPUT);
digitalWrite(PIN_QWIIC_POWER, HIGH); // Turn on qwiic power.
// Start the I2C bus.
qwiic.begin();
qwiic.setClock(90000); // 100k and 200k do NOT work. All others I've tried DO work.
setQwiicPullups(1); // Set pull up resistors to 1.5k. I've tried the other values too.
delay(500); // Seems like qwiic.begin() requires some time to finish.
lidarBegin(ADDR_LIDAR, qwiic);
Serial.println("Finished setup.");
}
void loop() {
float distance_cm;
// getDistance() returns the distance in cm.
distance_cm = myLIDAR.getDistance();
Serial.print(distance_cm);
Serial.print(" cm");
Serial.println();
delay(100); // Don't hammer the I2C bus.
}
//check if LIDAR will acknowledge over I2C
void lidarBegin(const byte address, TwoWire &qwiic) {
if (myLIDAR.begin(address, qwiic) == false) {
Serial.printf("LIDAR at address 0x%02X is missing.\r\n", address);
} else {
Serial.printf("LIDAR at address 0x%02X acknowledged!\r\n", address);
}
}
// Setup the values for the I2C pull up resistors. This code was taken from
// I2C_Detector.ino in the Artemis OpenLog repo.
void setQwiicPullups(uint32_t qwiicBusPullUps)
{
//Change SCL and SDA pull-ups manually using pin_config
am_hal_gpio_pincfg_t sclPinCfg = g_AM_BSP_GPIO_IOM1_SCL;
am_hal_gpio_pincfg_t sdaPinCfg = g_AM_BSP_GPIO_IOM1_SDA;
if (qwiicBusPullUps == 0)
{
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; // No pull-ups
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE;
}
else if (qwiicBusPullUps == 1)
{
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K; // Use 1K5 pull-ups
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K;
}
else if (qwiicBusPullUps == 6)
{
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_6K; // Use 6K pull-ups
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_6K;
}
else if (qwiicBusPullUps == 12)
{
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_12K; // Use 12K pull-ups
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_12K;
}
else
{
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_24K; // Use 24K pull-ups
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_24K;
}
pin_config(PinName(PIN_QWIIC_SCL), sclPinCfg);
pin_config(PinName(PIN_QWIIC_SDA), sdaPinCfg);
}