Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Have a way to test if an SSD1306 Oled display is present #59

Open
hlide opened this issue Apr 6, 2019 · 9 comments
Open

Have a way to test if an SSD1306 Oled display is present #59

hlide opened this issue Apr 6, 2019 · 9 comments

Comments

@hlide
Copy link

hlide commented Apr 6, 2019

My project can use several displays and an SSD1306 OLED display is not mandatory. But if I try to call the begin method, it freezes my firmware as I use your version I²C. So I have no practical way to detect an SSD1306 controller is present through your interface. I notice there is an active polling to check an ACK after sending a command. Wouldn't it be okay to poll a certain amount and abort with a boolean telling if it was ACKed? At least begin may return a boolean to say if a SSD1306 was able to answer while the rest of interface may stay unchanged.

Regards.

@DirtyEngineer
Copy link

This can be be done outside of this library but still along the same lines as your suggestion. Here is an example of how I have done it in the past.

const uint8_t OLED_I2C_ADDRESS = 0x3C;
bool oled_is_present = false;

void setup() {
    Wire.begin();
    Wire.beginTransmission(OLED_I2C_ADDRESS);
    if (Wire.endTransmission() == 0) { // OLED is present
        oled_is_present = true;
        oled.begin(&Adafruit128x64,OLED_I2C_ADDRESS);
        oled.setFont(System5x7);
        oled.clear();
    }
 }

@hlide
Copy link
Author

hlide commented Apr 6, 2019

Thanks for the suggestion. However, I would like avoid using Wire explicitely as much as possible but I guess it could be a workaround especially if Wire library is already inplicitely in use in my other libraries.

@bgrigoriu
Copy link

Hi,
Is there a workaround not using the Wire library (too "heavy" for the memory I have).

@greiman
Copy link
Owner

greiman commented Jul 4, 2021

There is a small custom driver for AVR on boards like Uno. See this example.

SPI displays use less memory also.

On Uno with the 128x64 examples:

Wire

Sketch uses 4948 bytes (15%) of program storage space. Maximum is 32256 bytes.
Global variables use 323 bytes (15%) of dynamic memory, leaving 1725 bytes for local variables. Maximum is 2048 bytes.

My I2C driver

Sketch uses 3152 bytes (9%) of program storage space. Maximum is 32256 bytes.
Global variables use 108 bytes (5%) of dynamic memory, leaving 1940 bytes for local variables. Maximum is 2048 bytes.

An SPI display

Sketch uses 3500 bytes (10%) of program storage space. Maximum is 32256 bytes.
Global variables use 108 bytes (5%) of dynamic memory, leaving 1940 bytes for local variables. Maximum is 2048 bytes.

@bgrigoriu
Copy link

This is exactly what i used. It works very VERY well. Thanks a lot.
However the sketch stops when the display is not present.
I was looking for a way to test if the display is present or not. But the solution offered by DirtyEngineer needs the wire library.

@greiman
Copy link
Owner

greiman commented Jul 4, 2021

Try the following function to check for an I2C device that responds to a zero length write. Should give the same result as DirtyEngineer's method.

// Retrun true if device responds to write.
bool i2cCheck(uint8_t i2cAdd) {
  bool rtn;
  AvrI2c i2c;
  i2c.begin();
  // low bit zero starts write, low bit 1 starts read.
  rtn = i2c.start(i2cAdd << 1);
  i2c.end();
  return rtn;
}

@bgrigoriu
Copy link

bgrigoriu commented Jul 4, 2021 via email

@greiman
Copy link
Owner

greiman commented Jul 4, 2021

Yes it should work for other devices.

Here is a debug program I used for AvrI2c. It prints two times the what Arduino uses for an address. The I2C bus specification specifies that in standard-mode I2C, the slave address is 7-bits long followed by the read/write bit.

// See which addresses respond to a start condition.
#include <AvrI2c.h>

AvrI2c i2c;

//------------------------------------------------------------------------------
void setup(void) {
  Serial.begin(9600);

  uint8_t add = 0;
  i2c.begin();
  // try read
  do {
    if (i2c.start(add | I2C_READ)) {
      Serial.print("Add read: ");
      Serial.println(add, HEX);
      i2c.read(true);
    }
    i2c.stop();
    add += 2;
  } while (add);

  // try write
  add = 0;
  do {
    if (i2c.start(add | I2C_WRITE)) {
      Serial.print("Add write: ");
      Serial.println(add, HEX);
    }
    i2c.stop();
    add += 2;
  } while (add);

  Serial.println("Done");
}
void loop(void){}

@bgrigoriu
Copy link

bgrigoriu commented Jul 4, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants