My Arduino needs to sometime request yaw, pitch, roll angles from Razor via I2C (unfortunately all serial ports in use and can’t be used).
I’m able to use Wire.requestFrom(0x68) and Razor firmware handles this request and sends Yaw, Pitch, Roll angles back, but… Arduino receives strange data (seems - from gyro sensor).
Documentation on mpu9250 chip says it has 2 I2c buses (external and aux) and hide gyro/accel on aux bus, acts as master to gyro/accel, the library code use following line:
mpu_set_bypass(1); // Place all slaves (including compass) on primary bus
I’ve tried to play with mpu_set_bypass(0)/mpu_set_bypass(1) to lock/unlock bus but without any result.
In scenario, when Arduino is slave and Razor is master and acts as pump (periodically sends angles to slave address), all works fine, but ths scenario works when just only Razor connected to i2C bus, any additional device requires Arduino to act as master and their libraries just run Wire.begin (instead of Wire.begin(ARDUINO_SLAVE_ADDRESS)). That’s not so ideal scenario.
So, is it possible to send data from Razor via I2C when Arduino makes request (Wire.requestFrom(0x68)), Razor uses Wire handler (Wire.onRequest(ProcessRequest)) and writes some data back by using Wire.write() and Arduino receives it? May be I need write something to Razor before request, to make it working? Any help appreciated.
The Razor isn’t setup to do this, but with the right custom firmware it might work.
I think it would be a lot easier for you to just use a [MPU-9250 breakout. That’s the same sensor that’s on the Razor but doesn’t include all the SAMD21 or SD card slot.](https://www.sparkfun.com/products/13762)
I’m trying to make Razor to do all his work with good discretion, it should constantly calculate and provide data on request (client/server), so just imu chip - not so good for me (and of course I’m able to get sensor data from Razor via i2c just by using standard library or ahrs lib).
The main question is: when Razor is a master I’m able transfer data to Arduino, but when Razor is a slave and request data from Razor it’s impossible? Probably there is some solution to do this (to make mpu9250 silent/turned off at request time? ).
PS: I’ve tried to post the code of 2 scenarios (working and desired), but getting 403 Forbidden error. Is this connected to size/length of reply message? Is it possible to post formatted code here? I think it would be useful to find a solution and make i2c as second protocol (and fast) to transfer data outside Razor.
I just took a look at the [Razor schematic. Sounds like you are using I2C through the Qwiic connector which is the same I2C bus that the MPU is on - that’s why you are talking about shutting down the MPU right?
Have you considered using an additional SERCOM to handle I2C completely separately? Pins 10, 11, 12, and 13 are connected to SERCOM 1 of the SAMD21 which is not used for anything else and they are exposed on a header on the Razor. You might be able to set that up as an I2C/SPI slave/master and use it without worrying about the MPU.
P.s. you can use code tags to format code. They look like this: (without spaces) [ code ] your code here [ / code ]. You can do the same to format URLs [ url=address ] text to display [ / url ]](https://cdn.sparkfun.com/assets/learn_tutorials/5/6/7/sparkfun-9dof-razor-imu-v30-schematic.pdf)
Yes, the MPU has the ability to act as its own I2C master for sensors on the auxiliary I2C lines - however on the Razor those are not even connected. In order to tell the MPU what to do with the auxiliary lines it needs to be configured by a master device first so I don’t think that will be directly applicable to your problem.
To poll the MPU the SAMD21 uC on the Razor must act as a master - this allows the Razor to do number-crunching for you. Then you want the Arduino to be able to ask the Razor for AHRS data on a whim - so that means the Arduino must be the master. The simplest way to do this is to use an additional SERCOM on the Razor to serve as the I2C slave.
To use an additional SERCOM port on the Razor you will need to follow a guide like [this one. You should be able to start that SERCOM-based I2C port in slave mode by calling “YourWire.begin(DESIRED_SLAVE_ADDRESS);”](https://learn.sparkfun.com/tutorials/adding-more-sercom-ports-for-samd-boards/all)
Thanks for the explanation, I’ll try it. But I’ve some doubts: the SparkFunMPU9250-DMP library runs Wire.begin() in MPU9250_DMP::begin(void) method. If I’ll use Wire.begin(DESIRED_SLAVE_ADDRESS) proposed, that’s just overrides Wire.begin() and makes mpu unable to work correctly, isn’t it? Or I should create new object Wire mywire? So, is it possible to create such slave connection on default Razor i2c pins (not using additional SERCOM pins) with new Wire (especially when I’ve no plans to use external sensors on these default pins)? I think I’ll try it also before SERCOM usage. Again, thank you, I’ll let you know about results.
Yes, you would need to create a new TwoWire object called (for example) “MyWire.” This will need to be associated with other pins because otherwise it would interfere with or override the default I2C pins which are used to communicate with the MPU.
So:
-
I’ve connected from Arduino to Razor 4 wires: 3.3v, Gnd, 13(SCL) and 11(SDA).
-
Used on Razor following initialization code(according to instructions ) from: [Adding More SERCOM Ports for SAMD Boards and from: [Samd21 Schematics.
-
Init new instance:
#define I2C_PIN_SDA 11
#define I2C_PIN_SCL 13
TwoWire razorWire(&sercom1, I2C_PIN_SDA, I2C_PIN_SCL);
- In Razor’s setup:
#define I2C_RAZOR_SLAVE_ADDRESS 0x09
razorWire.begin(I2C_RAZOR_SLAVE_ADDRESS);
razorWire.onRequest(ProcessWireRequest);
// Assign pins I2C_PIN_SDA & I2C_PIN_SCL to SERCOM functionality
pinPeripheral(I2C_PIN_SDA, PIO_SERCOM);
pinPeripheral(I2C_PIN_SCL, PIO_SERCOM);
- So, let’s try to request something from Arduino:
int dsize = Wire.requestFrom(I2C_RAZOR_SLAVE_ADDRESS, MSG_SIZE);
- Unfortunately request returns 0.
What’s wrong with this code?](https://cdn.sparkfun.com/assets/learn_tutorials/5/6/7/sparkfun-9dof-razor-imu-v30-schematic.pdf)](Adding More SERCOM Ports for SAMD Boards - SparkFun Learn)
Modified code SERCOM1_handler, required for slave i2c role, not for master.
Unfortunately it doesn’t work. What else?
Good news: Arduino-master, Razor-slave i2c SERCOM code works!
There was a problem with following code in setup():
#if DEBUG
SerialPort.begin(115200);
while (!SerialUSB) ; // wait for serial port to connect
#endif
When USB is not connected, it’s just stucked (eternal loop) there (with DEBUG condition true).
So, this is finally working code: [VIEW CODE
Special thanks to liquid.solder who’s pointed me in right direction.
PS: As I saw this problem is regular and posts of some SparkFun customers remain unanswered/solved in years. So, SparkFun guys, please add to SAMD21 boards libs(including, no doubts, your great device - Razor) examples of intercommunication between Razor(or SAMD21 board) and Arduino, ESP32 and other SAMD21 boards, via Serial, I2C and SPI interfaces, it will just extend usage of your products. Please use my code as you want(modify, improve, use it in your tutorials), without any authorship(that just compilation of different samples, opininons, docs and Razor’s Wire.h/.cpp files research) to add as example of such intercommunications. Of course, i think month later, I’ll just delete it from my docs, so somebody - publish it here (I’m just getting 403 error)](RAZOR Slave I2C connection with ARDUINO(SERCOM usage))
Awesome Randy, nice work. We appreciate that you’ll share the code. I will try to publish it in this thread. Ok, I got a 403 as well. Instead I have attached your code as an example under the ‘Documents’ section of the product page. It is hosted on our website now so anyone can download it [here](https://cdn.sparkfun.com/assets/6/3/8/e/5/RazorI2CSlaveExample.zip)