I have been prepping for a project and I am working with the u82g library (I am guessing it comes from here via the arduino library manager GitHub - olikraus/u8g2: U8glib library for monochrome displays, version 2), so far it is all good on my tests with one display. Multiple displays are also working well, but I don't really understand the code and want to work with an array of the screens.
based on the examples I can use my screens with this code:
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); // Arduino Due and single OLED
void setup(void) {
u8g2.begin();
}
void loop(void) {
u8g2.clearBuffer(); // clear the internal memory
u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
u8g2.drawStr(0,10,"Hello World!"); // write something to the internal memory
u8g2.sendBuffer(); // transfer internal memory to the display
delay(1000);
}
But I am stuck on either creating an array of OLEDs - nothing I have tried seems to work, or using this code in another class (using a .h and .cpp file).
I have searched a lot and found that multiple displays are supported (and I tested it and it does work), but the only examples I find are declaring them one by one
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g21(U8G2_R0, U8X8_PIN_NONE); // Arduino Due and single OLED
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g22(U8G2_R0, U8X8_PIN_NONE); // Arduino Due and single OLED
And this:
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2[8];
u8g2[0](U8G2_R0, U8X8_PIN_NONE);
or this:
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2[8](U8G2_R0, U8X8_PIN_NONE);
Don't not work for me.
It would be great if anyone can point me in the right direction.
Cheers
Fred
I am guessing that you want to use two SSD1306 displays on a Due.
Each needs 1kB SRAM for a full-size buffer.
The Due has sufficient SRAM.
It will hurt your head less with names like OLED1 and OLED2.
But if your project is a natural candidate for arrays, you could use an array with two elements.
You need to set one SSD1306 as Slave address = 0x3C and the other as 0x3D
And configure u8glib2 for each OLED.
Personally, I would put all I2C devices on the same I2C bus.
However the Due has got two independent I2C buses. You will need to study the docs to see how to use separate buses (if that is what you want).
David.
I am being kind of ambitious and want to use 10 displays, (afaik there is plenty of sram). I will use a single 12c bus and 2 i2c multiplexers. My planning for addressing is ok (I can set the start address of one of the multiplexers via some pullup pins and then have enough address space to access all the screens).
The issue I am having is more about creating an array as it will make my code manageable, but I don't understand how to do this with the constructor. Ideally I would like to actually have a class for each of my modules (containing a motor, a led, a button and a screen). But this is also eluding me as I cannot seem to be able to declare a constructor in my own class that contains the constructor of the display. I will clean some code and post it later.
** maybe I misunderstood this tip though:
You need to set one SSD1306 as Slave address = 0x3C and the other as 0x3D
And configure u8glib2 for each OLED.
Could you give an example of what that would look like in code? Maybe it does address my problem.
Thanks for the tips anyway.
If you want 10 independent displays, I suggest that you use the SPI version. Then you can put all ten on the same SPI bus. 10 separate /CS pins. An array of u8g2[10]
The Due has plenty of GPIO pins and plenty of SRAM for buffers.
You should think carefully about ten 128x64 screens. How would you fit them on a panel?
How easy to read?
A single 480x320 colour TFT screen with Touch might be more attractive and easier to use.
You seldom want to view 10 similar tiny displays.
You could show one large graphic that is the focus of your attention. The 9 smaller graphics can be brought into view as required.
I2C slaves are fine when you can allocate ten separate addresses. The SSD1306 has only 0x3C and 0x3D.
David.
I am stuck with 12c but with a multiplexer like this addressing is fine.
It will be a pretty large device, I am making the prototype with the above board (and a few others for testing like a few varieties of Hbridge). As the controller will be a 8 way channel strip based controller used for live performance it is pretty important to have a dedicated display for each strip (each strip has a motorised fader, 2 buttons and a screen I got the screens from Ali express and they work perfectly). The second 2 screens are for some other status information. The screens are 128X32 and very compact , not much wider than the full bulk of the faders and buttons they relate to.
After the prototyping I will ditch the adafruit board and print a circuit board with all the components combined to reduce the size, but again in this context smaller is not better, it is about usability in a specific situation.
The breakout board looks fairly easy. I2C bus lines should be short. I2C is designed for connecting devices all on one pcb.
I am not sure how to use the I2C multiplexer with the regular library(s).
Configure once and all subsequent "address" go to a specific device. Should be easy.
The SPI approach will always get the correct class object transparently.
The multiplexor will need you to insert a fresh "address-device#" sequence before changing object.
David.
The multiplexer is easy and gives each screen a unique address, however, to stick to my actual question, I am still wondering how to properly make an array of screens using the u82g library, in case anyone who knows passes by here.
Here is an example that uses two different U8g2 objects:
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI oled1(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
U8G2_SSD1306_128X64_NONAME_F_HW_I2C oled2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
U8G2 *screen[] = { &oled1, &oled2, }; // access via pointer array
U8G2 object[] = { // access via object array
U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R0),
U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R0),
}; // access via object array
void setup(void) {
oled1.begin();
oled2.begin();
object[1].begin(); //this is same physical I2C screen as oled2
}
void loop(void) {
oled1.clearBuffer(); // clear the internal memory
oled1.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
oled1.drawStr(0, 10, "Hello World!"); // write something to the internal memory
screen[0]->drawStr(0, 20, "SPI interface");
oled1.sendBuffer(); // transfer internal memory to the display
delay(1000);
screen[1]->clearBuffer(); // clear the internal memory
screen[1]->setFont(u8g2_font_ncenB08_tr); // choose a suitable font
screen[1]->drawStr(0, 10, "Hello World!"); // write something to the internal memory
screen[1]->drawStr(0, 20, "I2C pointer");
screen[1]->sendBuffer(); // transfer internal memory to the display
delay(1000);
object[1].clearBuffer(); // clear the internal memory
object[1].setFont(u8g2_font_ncenB08_tr); // choose a suitable font
object[1].drawStr(0, 10, "Hello I2C!"); // write something to the internal memory
object[1].drawStr(0, 30, "I2C object");
object[1].sendBuffer(); // transfer internal memory to the display
delay(1000);
}
I have shown two different names for two different objects of different classes.
If I had two different objects of the same class, I could declare an array of two objects. And reference with array notation.
I could also reference different objects with pointer notation.
Since you are going to multiplex them it seems unnecessary to have separate objects. You could simply use one object which you display on whichever globally selected screen you have chosen.
David.
Edit. Added global pointer array. Added pointer example statements.
Edit. Added global object array. Added object example statements.
fredaudio:
The multiplexer is easy and gives each screen a unique address, however, to stick to my actual question, I am still wondering how to properly make an array of screens using the u82g library, in case anyone who knows passes by here.
Do you mean this:
u8g2 screens[] =
{
u8g2(/* parameters /),
u8g2(/ parameters /),
u8g2(/ parameters /),
u8g2(/ parameters */)
};