I2C setClock Does not appear to be Standard way to setClock

Looking at the Wire code for the R4 it appears that setClock(frequency) is not operational, i.e., frequency can be passed but code does not translate to the i2c rate needed.

In wire.cpp


  if(is_master) {
    if((WireSpeed_t)ws == SPEED_STANDARD) {
        m_i2c_cfg.rate                    = I2C_MASTER_RATE_STANDARD;
    }
    else if((WireSpeed_t)ws == SPEED_FAST) {
        m_i2c_cfg.rate                    = I2C_MASTER_RATE_FAST;
    }
    else if((WireSpeed_t)ws == SPEED_VERY_FAST) {
        m_i2c_cfg.rate                    = I2C_MASTER_RATE_FASTPLUS;
    }

  }

ws is passed as a uint32_t but when used to set the cfg.rate it is converted to the WireSpeed_t enumerator:

typedef enum {
  SPEED_STANDARD = 0,  //100 kHz
  SPEED_FAST,      //400 kHz
  SPEED_VERY_FAST  //1 Mhz
} WireSpeed_t;

which will always fail if just a frequency is passed as is used in most sketches and libraries using I2C.

I can not not test directly as I won't have a minima until tomorrow and a wifi until the day after. But if I extract the code and test on different arm board:

typedef enum {
  SPEED_STANDARD = 0,  //100 kHz
  SPEED_FAST,      //400 kHz
  SPEED_VERY_FAST  //1 Mhz
} WireSpeed_t;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(5000);
  speed(SPEED_STANDARD);
  speed(400000);
  speed(1000000);
  speed(75000);
}

void loop() {
  // put your main code here, to run repeatedly:

}

void speed(uint32_t ws) {
  if((WireSpeed_t)ws == SPEED_STANDARD) {
    Serial.println("wire set to 100khz");
  }
  else if((WireSpeed_t)ws == SPEED_FAST) {
    Serial.println("wire set to 400khz");
  }
  else if((WireSpeed_t)ws == SPEED_VERY_FAST) {
    Serial.println("wire set to 1000khz");
  } else {
    Serial.println("Not supported");
  }
}

I get

wire set to 100khz
Not supported
Not supported
Not supported

I don't think this is the desired behaviour. Would think you would pass the frequency and code would check and set the correct rate. Also would have thougth that if you passed an incorrect frequency it would either default to the closest freq and/or return an error/message.

Will be testing I2C more when I get the boards.

I will have to try this out.. Although may wait until morning!

That is a bug.

According to the documenation, the parameter for Wire.setClock() is the frequency: setClock() - Arduino Reference

I think that it also should be possible to select 50 kHz or 231 kHz. If those values are not accepted, then at least they should be translated to one of the supported values.

Thanks for pointing this out. Our team has put together a PR to fix this issue.

@mario-r
Thanks for quick turn around on this thought it would take longer to get it fixed. As a said will be playing with I2C more when I get my boards (today and tomorrow I hope).

One other potential issue with I2C that may crop up is clock stretching which may be needed for some devices such as the BNO055 and BNO080 which are rather popular IMU's. But that is another issue.

I think that clock pulse stretching is included in the hardware on most processors.

The Arduino Uno works well as a I2C Slave. You can use that to test the clock pulse stretching if you have a oscilloscope or Logic Analyzer.

Sometimes a unknown device which uses its own software I2C signals does not support clock pulse stretching.

Thanks @Koepel will check it out later today - working on another potential issue to improve usability.

I finally got my R4 minima and decided to test your changes to Wire.h and Wire.cpp So downloaded the lates wire changes from the i2c_setSpeed branch. Using a MPU9250 with BolderFlight's IMU library (well tested on other boards) ran it at 100khz and 400khz. :
100khz:

Looks like maybe 90khz but at 400khz


Looks like we are getting about 256khz.

By comparison a Teensy 4.1:

Using a salae 16 LA.

UPDATE: Decided to check what I2c looked like on Metro Express M0


Pretty much looks like the T4.1 so something is off.

1 Like

100k seems to be ok, but reworked the 400k settings;

        case I2C_MASTER_RATE_FAST:
          m_i2c_extend.clock_settings.brl_value = 12;
          m_i2c_extend.clock_settings.brh_value = 11;
          m_i2c_extend.clock_settings.cks_value = 0;
          break;


seems a bit better.

Also not sure 1Mhz i2c is supported for the m4a1 chip. Don't see it in the RM.

Hi everyone,
I am not a hardware specialist, but this is the closest topic to the problem I encounter with the Arduino R4 WiFi.
I am using the 9 axis Motion shield (with the Bosh BNO055) , suggested as compatible on the arduino website. I am also using the suggested
Arduino_NineAxesMotion (GitHub - arduino-libraries/Arduino_NineAxesMotion: 9 Axes Motion Shield Library).
Consider that I am working on the "Accelerometer" example sketch.
What I see is that, uploading the sketch on a standard Arduino uno R3, everything goes very smoothly and the readings can be perfomed with a StreamPeriod of 20 ms.
However, when I upload the sketch on the R4 Wifi, the stream of data on the serial monitor is very slow (higher than 4 seconds but not constant).
I tried to look for elements in the library that could suggest changes for the new board, but every function call of the library seems coherent to me for the R4 platform.
Although I do not have instruments to try myself my hypothesis, I am guessing something not going smoothly on the I2C communication and the above comment from @Merlin513 seems to me related to this problem. What do you think ?
Thanks.

@framoc

I have been testing with the BNO055 and BNO080 on Wire and better on wire1. However, with that said I am not using the library that you mentioned. I am using the Adafruit BNO055 library along with their breakout board (but should work on others).

Another caveat is that in the released core setClock(100000) and setClock(400000) does not work. There is a PR in work that should fix that.

Again guessing here not know what breakout board you are using. If I get some time later with hook it up and try the lib you referenced.

EDIT: I did just notice this in the repo that you are using readme:

Note: this library is deprecated and no longer maintained.

So you may want to think about a different library.

@Merlin513
thank you for the quick feedback. I am using the 9 axis motion shield from the Arduino Store and the library is the one they suggest on the shield page. I am also planning to buy an adafruit shield to try the sensor on the new arduino board.
Were you able to make the sensors working with the adafruit library ? Because I tried it without success. In particular, I was always getting zero output values on the serial monitor.

This is the breakout board I am using from adafruit, Adafruit 9-DOF Absolute Orientation IMU Fusion Breakout - BNO055 : ID 2472 : $34.95 : Adafruit Industries, Unique & fun DIY electronics and kits and yes I am getting data from it.

Strange that its not working - I don't have one of those shield so I can't really test.

@framoc
I just tried the library you pointed to in your post and was not seeing any updates from the breakout board but when I added the following after Wire.begin(); I am now seeing data streaming smoothly. Add this:
Wire.setClock(I2C_MASTER_RATE_FAST);

1 Like

I've already tried this option since I am really convinced that the problem is in communication. Look at the output of the serial monitor
2...1...
Time: 10042ms aX: 0.30m/s2 aY: 0.72m/s2 aZ: 9.45m/s2 lX: 0.00m/s2 lY: 0.72m/s2 lZ: 9.45m/s2 gX: 0.00m/s2 gY: 0.00m/s2 gZ: 0.00m/s2 C: 0
Time: 17378ms aX: 0.30m/s2 aY: 0.72m/s2 aZ: 9.45m/s2 lX: 0.00m/s2 lY: 0.72m/s2 lZ: 9.45m/s2 gX: 0.00m/s2 gY: 0.00m/s2 gZ: 0.00m/s2 C: 0
Time: 24714ms aX: 0.30m/s2 aY: 0.72m/s2 aZ: 9.45m/s2 lX: 0.00m/s2 lY: 0.72m/s2 lZ: 9.45m/s2 gX: 0.00m/s2 gY: 0.00m/s2 gZ: 0.00m/s2 C: 0

I am getting something, but the time between each reading is absolute no sense in my opinion. I am also looking at the differences between the schematics between the two shields. apart from the logic level converter, they seem quite similar to each other. But I am not an expert on that. Really do not understand the problem. The shield is performing good on the R3 and not on the R4

I was seeing the same thing until I added setClock but I also have the draft PR incorporated for I2C. You might try incorporating it and see if that helps: Wire: fix setClock by facchinm · Pull Request #46 · arduino/ArduinoCore-renesas (github.com)

Until that gets incorporated not sure what else can be done. Mentioned this in the first post.

You should have not suggest me that :grin:
Now I am in the middle of an interior conflict.
I am relieved because it is possible that it will work soon and that I was quite close to identify the problem.
On the other side, I would like to try the new Wire lib to understand if that solves my problem.
But I do not know how to download the new wire and try on my arduino.

Wire.zip (7.8 KB)
Unzip the two files into the Wire library and you have the update.

If on a windows machine:
C:\Users\xxx\AppData\Local\Arduino15\packages\arduino\hardware\renesas_uno\1.0.2\libraries\Wire

where xxx is your user name in windows.

Dear Merlin..... IT WORKS !!!
I am really excited about that !!
Using the patch of the modified Wire library and setting the clock frequenzy to 400 kHz with the command
Wire.setClock(I2C_MASTER_RATE_FAST);
after Wire.begin();
it seems i am receiving data from the BNO055. Interested in understanding how fast I can now poll the IMU with the new board. Anyway, I will test it a little bit further and post here news.
I don't know how we could highlight this result in the forum to help other people that may encounter the same problem. The topic, initially was not on the 9 Axis Motion shield.

@framoc - glad it worked for you.

1 Like