greiman / SSD1306Ascii

Text only Arduino Library for SSD1306 OLED displays
MIT License
505 stars 121 forks source link

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

Open hlide opened 5 years ago

hlide commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 3 years ago

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

greiman commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

Thanks !! If I understand correctly that could eventually be applied to other I2C devices !


From: Bill Greiman @.> Sent: Sunday, July 4, 2021 7:08 PM To: greiman/SSD1306Ascii @.> Cc: bgrigoriu @.>; Comment @.> Subject: Re: [greiman/SSD1306Ascii] Have a way to test if an SSD1306 Oled display is present (#59)

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; }

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/greiman/SSD1306Ascii/issues/59#issuecomment-873627120, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AST5TZ2QBN3XK264XKGAVG3TWCISHANCNFSM4HEAELSQ.

greiman commented 3 years ago

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 commented 3 years ago

Thanks !! I really learned something today.

Bogdan


From: Bill Greiman @.> Sent: Sunday, July 4, 2021 7:26 PM To: greiman/SSD1306Ascii @.> Cc: bgrigoriu @.>; Comment @.> Subject: Re: [greiman/SSD1306Ascii] Have a way to test if an SSD1306 Oled display is present (#59)

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 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){}

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/greiman/SSD1306Ascii/issues/59#issuecomment-873629630, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AST5TZ5FO6UCPVYXNU5WF53TWCKTBANCNFSM4HEAELSQ.