I've spent almost two days figuring out how to properly communicate with the internal sensors of the new Nano 33 BLE and Nano 33 BLE Sense boards via I2C. And because it took me so long, i wanted to share, what i've found out.
So, the main reason, why we can't properly communicate with the internal sensors via I2C is that one of the default I2C bus wires is set to control the power mode of some sensors and therefore blocking the default I2C bus for direct communication. Now that we know the problem, we can use the TwoWire class of the Wire.h library to switch to a secondary I2C bus in order to communicate with the sensors.
In order to do so, you simply have to add the following line
extern TwoWire Wire1;
after your #include <Wire.h>
statement and afterwards replace every Wire.something()
with Wire1.something()
.
For example here is a sketch showing you how to use the secondary I2C bus with the help of Wire1 to read and write to the accelerometer and gyroscope of the Nano 33 BLE (also works for the Nano 33 BLE Sense).
#include <Wire.h>
extern TwoWire Wire1; //Use TwoWire class to switch to seconds I2C bus!
//this read function works
uint8_t readRegister(uint8_t slaveAddress, uint8_t registerAddress) {
uint8_t registerData; //placeholder for register data
Wire1.beginTransmission(slaveAddress); //Initiate I2C communication with slave address
Wire1.write(registerAddress); //Set pointer to register address
Wire1.endTransmission(false); //Send buffer, but keep connection alive
Wire1.requestFrom(slaveAddress, (uint8_t)1); //Request one byte from the register the pointer was set to
registerData = Wire1.read(); //Read byte and copy its content to data placeholder variable
Wire1.endTransmission(); //End I2C communication
return registerData; //Return read data
}
//this write functions works (but only if register is writeable)
uint8_t writeRegister(uint8_t slaveAddress, uint8_t registerAddress, uint8_t registerValue) {
Wire1.beginTransmission(slaveAddress); //Initiate I2C communication with slave address
Wire1.write(registerAddress); //Set pointer to register address
Wire1.write(registerValue); //Overwrite register address the pointer is set to with new value
Wire1.endTransmission(); //End I2C communication
}
void setup(){
Serial.begin(9600); //Start serial communication
Wire1.begin(); //Initialize I2C Wire1
while (!Serial); //Wait for the serial monitor
Serial.println("Serial Started");
delay(50);
}
void loop(){
byte registerData = readRegister(0x6b, 0x1e); //Read CTRL_REG4 register of the LSM9DS1 accelerometer and gyroscope
Serial.print("Register value = "); //default value = 0x38
Serial.println(registerData, HEX);
delay(5000);
writeRegister(0x6b, 0x1e, 0x00); //Replace default CTRL_REG4 register value with 0x00
delay(5000);
}
I hope this was helpful to some of you.
Best regards,
paarn
PS: I have also attached a modified version of the I2C-scanner which works with the new boards to this thread.
i2c_scanner_for_nano_33_ble.ino (2.27 KB)