greiman / SSD1306Ascii

Text only Arduino Library for SSD1306 OLED displays
MIT License
500 stars 122 forks source link

begin with Slow i2c 100kHz mode #48

Open MasterBlatter opened 6 years ago

MasterBlatter commented 6 years ago

Hi, as I'm not interested in using high speed 400kHz i2c mode to drive the display, I actually add a beginSlow() in SSD1306AsciiAvrI2c.h There's another, method to don't use the fast mode?

void beginSlow(const DevType* dev, uint8_t i2cAddr) {
    m_nData = 0;
    m_i2cAddr = i2cAddr;

    m_i2c.begin(false);
    init(dev);    

 }
deladriere commented 6 years ago

I just do : Wire.setClock(2500000L); to change the i2c speed to my favorite speed (Yes I need High speed)

greiman commented 6 years ago

I will add a call to set the I2C speed. This is the function from the Wire library.

void twi_setFrequency(uint32_t frequency)
{
  TWBR = ((F_CPU / frequency) - 16) / 2;

  /* twi bit rate formula from atmega128 manual pg 204
  SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
  note: TWBR should be 10 or higher for master mode
  It is 72 for a 16mhz Wiring board with 100kHz TWI */
}

The comment implies this works from about 40 kHz to 444,000 kHz with FCPU = 16 MHz.

MasterBlatter commented 6 years ago

KK but I'm not using Wire, just SSD1306Ascii and SSD1306AsciiAvrI2c

greiman commented 6 years ago

The above function works on any AVR board without including Wire.

To set 100 kHz on a 16 MHz AVR board you can just add a line like this.

TWBR = 72;

I have added a setClock() call to the AvrI2c so you will be able do the following in the next version of SSD1306AsciiAvrI2c.

oled.setI2cClock(100000L);

deladriere commented 6 years ago

@greiman will oled.setI2cClock(100000L); affects communication with my other I2c devices too or just the SSD1306 ? I want to use different speeds for my various slower devices. Today I speed up the clock when talking to the SSD1306 and reduce the speed just after to allow my other devices to work

greiman commented 6 years ago

deladriere Changing the I2C frequency on an AVR board is global. There is a single TWBR baud rate register. You must set the I2C frequency in your program before using a device.

MasterBlatter I published an update that allows setting the I2C frequency with AvrI2c.

There are two methods. You can change the default frequency by editing SSD1306Ascii.h.

/** AvrI2c uses 400 kHz fast mode if AVRI2C_FASTMODE is nonzero else 100 kHz. */
#define AVRI2C_FASTMODE 1

You can call oled.setI2cClock(frequency) in your sketch.

deladriere commented 6 years ago

@greiman Thanks for the update My board is a SAMD21 clone and I cannot have a global change of speed because my other device is slower than the display. So I guess I'll stay with Wire.setClock(high-speed); before driving any SSD1306 command and Wire.setClock(low-speed); just after them

greiman commented 6 years ago

deladriere

I guess this is a universal problem for Wire on all boards.

Too bad the Wire library is not like SPI. The SPI beginTransaction() protocol insures each device uses the proper clock.