Multiple OLED Displays for Arduino

Hey everyone!

I’m very new to coding and Arduino’s so go easy on me! This is also my first post :slight_smile:

I’m currently setting up an Arduino as a plant monitor.

I’ve decided to go with an Arduino Uno Rev 3, with a Base Shield V2 attached for the Grove sensors/displays I’m using. My Grove OLED displays are 128x64, and there are 3 of them. I’m also using a Grove TH02 sensor and a Grove temperature sensor. There is a soil sensor yet to come, however my main objective is to get the TH02 values to display on an OLED display, and the temperature sensor values to display on another, with the third display free for when the soil sensor arrives. I’ve made a start on the code (an awful start, but still a start), and would really love some help on getting the TH02 sensor and temperature sensor to display values on 2 seperate OLED displays.

I’ve followed some steps from: http://forum.arduino.cc/index.php?topic=219419.30

Please excuse this atrocious code:

#include "U8glib.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <U8glib.h>
#include <Print.h>
#include "clib/u8g.h"
#define _CPP_U8GLIB
#include <Wire.h>
#include <SeeedOLED.h>
#include <TH02_dev.h>
#include "Arduino.h"
#include "Wire.h" 
#include <math.h>
int a;
float temperature;
int B=3975;                  //B value of the thermistor
float resistance;

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);
extern uint8_t I2C_SLA;

boolean redraw_display_one = false;
boolean redraw_display_two = false;
boolean redraw_display_three = false;

void setup()
{
  I2C_SLA = 0x078;
  u8g.firstPage();
  do
  {
    draw_message_one();
  }
  while(u8g.nextPage());

  delay(10);

  I2C_SLA = 0x07A; 
  u8g.firstPage();
  do
  {
    draw_message_two();
  }
  while(u8g.nextPage());

}

void loop()
{
  a=analogRead(0);
    resistance=(float)(1023-a)*10000/a; //get the resistance of the sensor;
    temperature=1/(log(resistance/10000)/B+1/298.15)-273.15;//convert to temperature via datasheet ;
    delay(1000);
       
  if (redraw_display_one)
  {
    I2C_SLA = 0x078;

    u8g.firstPage();
    do
    {
      draw_message_two();
    }
    while(u8g.nextPage());

    redraw_display_one = false;
  }

  if (redraw_display_two)
  {
    I2C_SLA = 0x07A;
    u8g.firstPage(); 
    do
    {
      draw_message_one();
    }
    while(u8g.nextPage());
    redraw_display_two = false;

  }
  
  unsigned long time = millis();
  
  if (time > 5000 && time < 5033)
  {
    redraw_display_one = true;
    redraw_display_two = true;
    redraw_display_three = true;
  }
}

void draw_message_one()
{
  u8g.setFont(u8g_font_fub14);
  u8g.drawStr(12, 28, "Temperature");
  u8g.setPrintPos(12, 58);
  u8g.print(temperature);
}

void draw_message_two()
{
  u8g.setFont(u8g_font_fub14);
  u8g.drawStr(12, 28, "Goodbye");
  u8g.drawStr(12, 58, "World");
}

Feel free to make major modifications or recommendations! Open to all sorts of criticism, especially considering my knowledge of coding and Arduinos is very minimal.

I also haven’t added the TH02 code, but here’s the example from it’s library:

#include <TH02_dev.h>
#include "Arduino.h"
#include "Wire.h" 
 
void setup()
{  
  Serial.begin(9600);        // start serial for output
  
  Serial.println("****TH02_dev demo by seeed studio****\n");
  /* Power up,delay 150ms,until voltage is stable */
  delay(150);
  /* Reset HP20x_dev */
  TH02.begin();
  delay(100);
  
  /* Determine TH02_dev is available or not */
  Serial.println("TH02_dev is available.\n");    
}
 

void loop()
{
   float temper = TH02.ReadTemperature(); 
   Serial.println("Temperature: ");   
   Serial.print(temper);
   Serial.println("C\r\n");
   
   float humidity = TH02.ReadHumidity();
   Serial.println("Humidity: ");
   Serial.print(humidity);
   Serial.println("%\r\n");
   delay(1000);
}

I suggest to use u8g2.
There are multiple options to setup two I2C OLEDs. You could either configure the OLEDs with two different I2C addresses or you can attach the OLEDs to two different sets of GPIOs and use U8g2 SW I2C feature.

Some hints are also mentioned in the U8g2 FAQ (SPI instead of I2C):

Oliver

I ran a sample code from the link you mentioned, however nothing is displayed onto the OLED. I think this is because the Base Shield V2 only supports I2C? This hat for the Arduino removes the need for a breadboard and jump wires, and instead uses "grove connectors".

First of all you need to figure out the correct connection and arguments for the u8g2 constructors. First, work with one OLED only.

Maybe also attach a picture of your setup.

Oliver

I tried running the "Hello World!" sketch located in the U8G2 Library, however it still did not display anything (using one display). I tried using the constructors provided in the sketch, however none of them seemed to work for the 128x64 OLED, even the SW I2C constructors. I'm most likely mucking up on my end, but I'm very new to this so it's difficult to see where I'm going wrong!

Here's a picture of my setup:

http://prntscr.com/k3u43c

Which constructor did you use? Did you at least tried HW I2C?

Oliver

I just arrived back home and thought I'd give it another go.. the 128x64 HW_I2C constructors seem to work fine:

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

U8G2_SSD1306_128X64_ALT0_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);   // same as the NONAME variant, but may solve the "every 2nd line skipped" problem

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 16, /* data=*/ 17);   // ESP32 Thing, HW I2C with pin remapping

However the other constructors for 128x64 don't seem to work at all.

Do you have any idea?

I assume the U8G2_SSD1306_128X64_NONAME_F_HW_I2C constructor is the one and only correct constructor for your display. If you want to use more than one, you need to modify the i2c address of your display (consult your display datasheet for this) and use the u8g2.setI2CAddress command in setup() procedure for the second u8g2 object.

Oliver

Spot on haha.

I have no idea about display datasheets haha! Is there somewhere I could refer to online about display datasheets? Otherwise the void setup() procedure is pretty straight forward.

Thank you so so much for your help!

I found that this code appears to light up all 3 OLED displays, however each OLED display reads 'One', instead of their respective number. I'm not sure if my addressing is incorrect or not. How could I change this code to display 'One', 'Two' and 'Three' to their respective OLED display?

#include "U8g2lib.h"
#include "Wire.h" //Library for I2C interface

U8G2_SH1106_128X64_NONAME_F_HW_I2C OLED_1(U8G2_R0, U8X8_PIN_NONE);
U8G2_SH1106_128X64_NONAME_F_HW_I2C OLED_2(U8G2_R0, U8X8_PIN_NONE);
U8G2_SH1106_128X64_NONAME_F_HW_I2C OLED_3(U8G2_R0, U8X8_PIN_NONE);

void setup() {
  OLED_1.setI2CAddress(0x3C * 2);        
  OLED_2.setI2CAddress(0x3D * 2);        
  OLED_3.setI2CAddress(0x7A * 2);        

  OLED_1.begin();
  OLED_2.begin();
  OLED_3.begin();
  OLED_1.setFont(u8g_font_6x10);
  OLED_2.setFont(u8g_font_6x10);
  OLED_3.setFont(u8g_font_6x10);
}

void loop() {
  static unsigned long oledTimer = millis(); //every 1000ms update the oled display
  if (millis() - oledTimer >= 1000) {
    oledTimer = millis();
    drawOLED_1();
    drawOLED_2();
    drawOLED_3();
  }
}

void drawOLED_1(void) {
  char buffer[10];
  OLED_1.clearBuffer(); // clear the internal memory
  OLED_1.setFont(u8g_font_6x10);
  OLED_1.drawStr(0, 10, "One");
  OLED_1.drawStr(80, 10, buffer);
  OLED_1.sendBuffer(); // transfer internal memory to the display
}

void drawOLED_2(void) {
  char buffer[10];
  OLED_2.clearBuffer(); // clear the internal memory
  OLED_2.setFont(u8g_font_6x10);
  OLED_2.drawStr(0, 10, "Two");
  OLED_2.drawStr(80, 10, buffer);
  OLED_2.sendBuffer(); // transfer internal memory to the display
}

 void drawOLED_3(void) {
  char buffer[10];
  OLED_3.clearBuffer(); // clear the internal memory
  OLED_3.setFont(u8g_font_6x10);
  OLED_3.drawStr(0, 10, "Three");
  OLED_3.drawStr(80, 10, buffer);
  OLED_3.sendBuffer(); // transfer internal memory to the display
}

Spot on haha.

I have no idea about display datasheets haha!

Where did you buy the OLED? Link?

I found that this code appears to light up all 3 OLED displays, however each OLED display reads 'One', instead of their respective number. I'm not sure if my addressing is incorrect or not. How could I change this code to display 'One', 'Two' and 'Three' to their respective OLED display?

You will not be able to connect 3 OLEDs. At least not with your board and an Arduino Uno as a microcontroller. This is because, there can only up to two SSD1306 based OLEDs on the same I2C bus (see the SSD1306 specification).

This OLED at least comes with some pictures. See the picture back side of the OLED:

https://www.ebay.com/itm/0-96-I2C-IIC-Serial-128X64-128-64-Blue-OLED-LCD-LED-Display-Module-for-Arduino/401395129024

It describes how to change the solder bridges for a specific I2C address. And: You can only select one of two addresses. This is because not more are possible.

Oliver

Here's the link to the OLED display:

https://www.seeedstudio.com/Grove-OLED-Display-0.96%26quot%3B-p-781.html

Oh... well that's tragic! I guess I've learnt from my mistakes! I just assumed that it could support however many OLEDs relative to the amount of I2C ports.

Oh right, okay. Well I also tried the same code I sent before but with 2 OLEDs, however the same thing happened. They both displayed 'One' instead of displaying 'One' for display one, and 'Two' for display two. Any idea why that may have still been the outcome?

WiccaWiccaWoo: Oh right, okay. Well I also tried the same code I sent before but with 2 OLEDs, however the same thing happened. They both displayed 'One' instead of displaying 'One' for display one, and 'Two' for display two. Any idea why that may have still been the outcome?

I assume both OLEDs are shipped with the same I2C address. You must physically change the I2C address for one of the OLEDs. Often this can be done by solder bridges on the PCB of the OLED module. Sometimes there is a jumper. In some other cases this is not possible at all (this is why I asked for a datasheet...)

Regarding the solder bridges, I quote myself:

This OLED at least comes with some pictures. See the picture back side of the OLED:

https://www.ebay.com/itm/0-96-I2C-IIC-Serial-128X64-128-64-Blue-OLED-LCD-LED-Display-Module-for-Arduino/401395129024

It describes how to change the solder bridges for a specific I2C address. And: You can only select one of two addresses. This is because not more are possible.

Oliver