Using Razor 9DOF via I2C as slave?

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)

liquid.soulder:
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?
[/quote]
As I’ve figured out: MPU acts as master to accel/gyro devices and control them via i2c master bus. It uses bypass mode to connect master and aux bus (extern i2c) to control external devices like barometer or something else.

The main thing “acts as master”, so Arduino in this can be external slave device.

But - in my code (Arduino is master), Arduino requests data by Wire.requestFrom and Razor handles it (blue led blinks)! But data transferred from Razor just not received by Arduino, instead of yaw, pitch, roll Arduino receives “noise” (I’ve tried to send 1,2,3,4,5 but received 12, 0, 3, 128,245 or nulls), probably from gyro. So I’m supposing if I make gyro/accel to don’t answer on request, I’ll probably get yaw, ptch, roll on i2c bus and Arduino.

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.

Unfortunately Razor library uses Wire.begin();(without specific address), so Razor acts as master. Yes it has 0x68 address, but I think If I'll use SERCOM way I'll just have the same problem. If Razor board would've its own i2c address, there is no problem with i2c usage master or slave roles at all. But I've no idea what to do with library to make it happen.

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 ]

[/quote]

I’ve prepared formatted with BBC tags code, and my reply stored in drafts but I can’t publish it - always 403 forbidden. I’ve tried to attach as .txt file - now it’s http error. I thnik there are some limitations.

Here you can view the code(I’ve uploaded it to Google drive):

[Code desired to work(Arduino is master and requests data, Razor just send data back on request)

and

[Code which works(Arduino is slave, Razor pumps data)](Razor i2c problem: Code which works - Google Docs)](Razor i2c problem: code desired to work - Google Docs)](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:

  1. I’ve connected from Arduino to Razor 4 wires: 3.3v, Gnd, 13(SCL) and 11(SDA).

  2. Used on Razor following initialization code(according to instructions ) from: [Adding More SERCOM Ports for SAMD Boards and from: [Samd21 Schematics.

  3. Init new instance:

#define I2C_PIN_SDA 11
#define I2C_PIN_SCL 13
TwoWire razorWire(&sercom1, I2C_PIN_SDA, I2C_PIN_SCL);
  1. 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);
  1. So, let’s try to request something from Arduino:
int dsize = Wire.requestFrom(I2C_RAZOR_SLAVE_ADDRESS, MSG_SIZE);
  1. 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)

Additionally:

  1. request not received on Razor, so the handler: ProcessWireRequest not called.

  2. blue led on d13 - is always on. Not so good port? I’ve tried D10-D12 pair also, same result. I’ve tried to set the same clock (Wire.setClock, razorWire.setClock - nothing)

Here is complete code on Razor: [VIEW CODE](Razor i2c: SERCOM additional i2c port - Google Docs)

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)