felias-fogg / SoftI2CMaster

Software I2C Arduino library
GNU General Public License v3.0
368 stars 100 forks source link

Bug with frequency I2C bus #60

Closed Deoptim closed 3 years ago

Deoptim commented 3 years ago

Hello. When I use OLED display with FPS(GyverOLED) benchmark and Arduino Pro Mini (16MHz/5V):

  1. With standard Wire.h library the FPS on OLED show ~30fps
  2. With SoftI2CMaster(SoftWire.h) library the FPS on OLED show ~26fps
  3. With SoftI2CMaster(SoftWire.h) library and parameter "I2C_CPUFREQ 6400000UL" the FPS on OLED show ~45fps

My parameters to replace standard Wire.h lib:

//===================================
// softwareI2C lib
#define I2C_HARDWARE 1
#define I2C_PULLUP 1
#define I2C_FASTMODE 1
#define I2C_CPUFREQ 6400000UL  //bug workaround (with this value is max I2C frequency, even with 4MHz MCU)
#define SDA_PORT PORTC // PORTC
#define SDA_PIN A4 // = A4
#define SCL_PORT PORTC // PORTC
#define SCL_PIN A5 // = A5
#include <SoftWire.h>
//===================================

Empirically, it was found that even the actual frequency of the MCU (8Mhz or 16Mhz) does not depend on the value 6400000UL - i.e. it is universal value for any MCU frequency and gives the maximum speed on the I2C bus.

Also tested with atmega8a (8MHz internal clock) and Arduino Pro Mini (8MHz/3.3V)

Wire.h ![Wire h](https://user-images.githubusercontent.com/5656726/130215211-b5801fb0-d9a3-4407-b584-c792a9a955b3.jpg)
Commented out "//#define I2C_CPUFREQ 6400000UL" ![hardware](https://user-images.githubusercontent.com/5656726/130215488-536c6703-d01f-4e15-8a3f-335861382c2e.jpg)
With "#define I2C_CPUFREQ 6400000UL" ![hardware_plus_6400000](https://user-images.githubusercontent.com/5656726/130215611-5a01c293-9d59-49f0-b76b-3db293312d12.jpg)
felias-fogg commented 3 years ago

Hi,

can you please explain what the bug is and what kind of fix you propose?

Best, Bernhard

felias-fogg commented 3 years ago

In any case, if you want to control the speed of TWI/I2C communication when using the hardware module (#define I2C_HARDWARE 1), then the best way to do that is to set the bit rate of the TWI module using the TWIBR register and the prescale value in the TWISR register (see function "fequency" in example/I2CShell.ino). When using the standard Wire library, also the setClock method will help.