Auto detect SSD1306,SH1106 and SH1107 display type #2088
Replies: 4 comments 3 replies
-
|
U8g2 had been designed as a write-only library. This is a design decision to have a common code base with SPI based displays (SPI based displays usually do not allow read operation). |
Beta Was this translation helpful? Give feedback.
-
|
I have managed to get an example of what I'm looking for, allowing one sketch to work for both a SSD1306 and a SH1106, after detecting the presence. I'm wondering if you could advise if there was a cleaner way to redirect the class name at run time, to remove the duplicated up user code. I.e. can i call one class in the user code (i.e. 'u8g2'), but redirect that to 'u8g2_1' or 'u8g2_2' programmatically at run time? #include <U8g2lib.h>
#include <Wire.h>
byte buffer[0];
int Type3C;
int Type3D;
bool flip = false;
U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2_1(U8G2_R0, /* reset=*/U8X8_PIN_NONE); //Type1
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2_2(U8G2_R0, /* reset=*/U8X8_PIN_NONE); //Type2
void setup() {
Wire.begin();
Serial.begin(9600);
// while (!Serial); // Leonardo: wait for Serial Monitor
delay(20);
for (byte address = 1; address < 127; ++address) {
Wire.beginTransmission(address);
byte error = Wire.endTransmission();
if (error == 0) {
if (address == 0x3C) {
Serial.print("OLED Display 0x3C, Type: ");
Type3C = DisplayType(address);
}
if (address == 0x3D) {
Serial.print("OLED Display 0x3D, Type: ");
Type3D = DisplayType(address);
}
}
}
switch (Type3C) {
case 1:
u8g2_1.begin();
u8g2_1.setFlipMode(flip);
break;
case 2:
u8g2_2.begin();
u8g2_2.setFlipMode(flip);
break;
default:
// statements
break;
}
}
void loop() {
switch (Type3C) {
case 1:
u8g2_1.firstPage();
do {
u8g2_1.setFont(u8g2_font_ncenB10_tr);
u8g2_1.drawStr(35, 24, "SH1106!");
u8g2_1.drawStr(15, 48, "Hello World!");
} while (u8g2_1.nextPage());
break;
case 2:
u8g2_2.firstPage();
do {
u8g2_2.setFont(u8g2_font_ncenB10_tr);
u8g2_2.drawStr(35, 24, "SSD1306!");
u8g2_2.drawStr(15, 48, "Hello World!");
} while (u8g2_2.nextPage());
break;
default:
// statements
break;
}
delay(1000);
}
int DisplayType(int address) {
Wire.beginTransmission(address); //Can't reliably read register on first try
Wire.write(0x00); //Can't reliably read register on first try
Wire.endTransmission(); //Can't reliably read register on first try
Wire.beginTransmission(address);
Wire.write(0x00);
Wire.requestFrom(address, 1); // This register is 8 bits = 1 byte long
if (Wire.available() > 0) {
Wire.readBytes(buffer, 1);
}
Wire.endTransmission();
buffer[0] &= 0x0f; // mask off power on/off bit
switch (buffer[0]) {
case 0x7 || 0xf: // SH1107
Serial.println("SH1107");
return 0;
// break;
case 0x8: // SH1106
Serial.println("SH1106");
return 1;
// break;
case 0x6: // SSD1306 6=128x64 display
Serial.println("SSD1306");
return 2;
// break;
case 0x3: // SSD1306 3=128x32 display
Serial.println("SSD1306");
return 3;
// break;
default:
Serial.print("UNKNOWN: 0x0");
Serial.println(buffer[0], HEX);
return -1; //Unknown
// break;
}
} |
Beta Was this translation helpful? Give feedback.
-
|
Arduino is C++, so you can create a base U8g2 base object and assign the desired constructor. U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2_1(U8G2_R0, /* reset=*/U8X8_PIN_NONE); //Type1
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2_2(U8G2_R0, /* reset=*/U8X8_PIN_NONE); //Type2
U8G2 *u8g2;
...
if ( isSSD1306 )
u8g2 = &u8g2_2;
else
u8g2 = &u8g2_1;
...
u8g2->begin();Now you can write your code with the u8g2 object insted. But: Instead of the "." syntax you need to use the "->" syntax. |
Beta Was this translation helpful? Give feedback.
-
|
Looks good 👍😀 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I know a similar question has been asked before, but I'm hoping for some help and advise on how to try and implement this.
Using a I2C display, It is possible to read the registers of an SSD1306,SH1106 and SH1107 to be able to detect presence, driver type, and address. See https://github.com/bitbank2/ss_oled
Is there any way that it could be possible to setup, or create a new display type that follows this kind of functionality with U8G2?
I believe this feature would be of great use to the community, as a group I'm collaborating is having issues with sellers mixing SSD1306 and SH1107 drivers within listings.
Further information:
The 3 displays in question can be set to either 0x3C or 0x3D
and the registers can be read to identify the display in question
https://github.com/bitbank2/ss_oled/blob/01fb9a53388002bbb653c7c05d8e80ca413aa306/src/ss_oled.cpp#L792-L830
Beta Was this translation helpful? Give feedback.
All reactions