OLED and BMP180 on I2C issue

Hi
I am using the Arduino Uno. I have a BMP180 sensor and an OLED that I want to connect to the Arduino. Both use the I2C. I have connected the BMP180 to pins A4 (SDA) and pin A5 (SCL) and the OLED to the I2C pins on the digital I/O side.
For the BMP180 I am using the Adafruit library (Adafruit_BMP085_Library) and for the OLED the U8glib library. The OLED is the SH1106.
If I upload the example sketch which just handles the BMP180 I get the correct results from the BMP180. If I just run the U8glib example sketch then the OLED works correctly. When I combine the logic in the two sketches only the BMP180 gives me the expected results, but the OLED just displays white (noise) on the screen.
I know that I2C can handle multiple devices and you just need to address then properly. I have checked in the In Adafruit_BMP085.h and the I2C Address for BMP180 is set as follows:
#define BMP085_I2CADDR 0x77
I cannot find any address specification in the U8glib.h, but on the back of the OLED are the following addresses:
0x78 and 0x7A

How do I get both devices on I2C to work correctly?
I am also connecting a DHT22 sensor, but fortunately that does not require the I2C.

My code is as follows (Note: I had to remove a lot of the commented text with the copyright information of the libraries just to be able to make the character limit for the post):

/*
Weather Station Unit
Version 1.0.0

Sensors:
DHT22 - Temperature and humidity
BMP180 - Atmospheric pressure, temperature, altitude

Display:
OLED Display

Uses a push button to change between temperature in Celsius and Fahrenheit.

Kobus Botha
25 October 2016
*/

//Add the required libraries
#include <Wire.h>
#include <Adafruit_BMP085.h>  //Required for the BMP180 sensor
#include <DHT.h>              //Required for the DHT22 sensor
#include <U8glib.h>           //Required for the OLED display



// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!)
// Connect GND to Ground
// Connect SCL to i2c clock - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 5
// Connect SDA to i2c data - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 4
// EOC is not used, it signifies an end of conversion
// XCLR is a reset pin, also not used here


//INFO ABOUT DEVELOPERS OF CODE FOR DHT22
/* How to use the DHT-22 sensor with Arduino uno
   Temperature and humidity sensor
   More info: http://www.ardumotive.com/how-to-use-dht-22-sensor-en.html
   Dev: Michalis Vasilakis // Date: 1/7/2015 // www.ardumotive.com */



Adafruit_BMP085 bmp;

//Constants
#define DHTPIN 2     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE); //// Initialize DHT sensor for normal 16mhz Arduino


//INFO ABOUT DEVELOPERS OF CODE FOR OLED DISPLAY
/*
  >>> Before compiling: Please remove comment from the constructor of the 
  >>> connected graphics display (see below).
  
  Universal 8bit Graphics Library, https://github.com/olikraus/u8glib/
  
  Copyright (c) 2012, olikraus@gmail.com
  All rights reserved.

  
*/


// setup u8g object, please remove comment from one of the following constructor calls
// IMPORTANT NOTE: The following list is incomplete. The complete list of supported 
// devices with all constructor calls is here: https://github.com/olikraus/u8glib/wiki/device
//U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9);  // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SH1106_128X64 u8g(4, 5, 6, 7); // SW SPI Com: SCK = 4, MOSI = 5, CS = 6, A0 = 7 (new blue HalTec OLED)
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); // I2C / TWI 
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST); // Dev 0, Fast I2C / TWI
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK); // Display which does not send ACK


const int buttonPin = 8;


//Variables
int buttonState = 0;
int previousButtonState = HIGH;
 
int chk;
float hum;  //Stores humidity value
float tempDHT22; //Stores temperature value read from DHT22
float tempBMP180; //Stores temperature value read from BMP180
long pressure; //Stores atmospheric pressure read fromBMP180
long seaLevelPressure;
float altitude;
float realAltitude;
float averageTemperature;   //Stores the average temperature of the two sensors
bool temperatureUnitCelsius = true;

bool useOLED = false;

  
void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);

  // Setup OLED Display
  setupOLED();

  bool devicesWorking = true;
  
  dht.begin(); 

  // Attempt to start the BMP180 sensor  
  if (!bmp.begin()) {
    // There is a problem with this device
    Serial.println("Could not find a valid BMP180 sensor, check wiring!");
    devicesWorking = false;
  }

  // There is a problem with one or more devices/sensors
  if (!devicesWorking)
  {
    // Loop infinitely
    while (1) {}
  }
}


  
void loop() {
  //Read button state (pressed or not pressed?)
  buttonState = digitalRead(buttonPin);

  // Check if the button state has changed
  if (buttonState != previousButtonState) 
  { 
    // Check if button is pressed.
    if  (buttonState == HIGH)
    {
      // Button is pressed. Change temperature unit.
      temperatureUnitCelsius = !temperatureUnitCelsius;
    }
  }
  previousButtonState = buttonState;
  
  // Get readings from BMP180
  tempBMP180 = bmp.readTemperature();
  pressure = bmp.readPressure();

  // Calculate altitude assuming 'standard' barometric
  // pressure of 1013.25 millibar = 101325 Pascal
  altitude = bmp.readAltitude();
  //Read the approximate calculated pressure at sea level
  seaLevelPressure = bmp.readSealevelPressure();
  // you can get a more precise measurement of altitude
  // if you know the current sea level pressure which will
  // vary with weather and such. If it is 1015 millibars
  // that is equal to 101500 Pascals.
  realAltitude = bmp.readAltitude(101500);
  
  // Read data and store it to variables hum and temp
  hum = dht.readHumidity();
  tempDHT22 = dht.readTemperature();

  // Calculate the average temperature from the two sensors
  averageTemperature = (tempBMP180 + tempDHT22) / 2;

  printData();

  if (useOLED)
  {
    draw();
  }

  delay(1000);
}



void setupOLED() {
  if (!useOLED)
  {
    return;
  }
  // flip screen, if required
  // u8g.setRot180();
  
  // set SPI backup if required
  //u8g.setHardwareBackup(u8g_backup_avr_spi);

  // assign default color value
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255,255,255);
  }
}


//Method to convert the temperature from Celsius to Fahrenheit
float Convert_CelsiusToFahrenheit(float tempCelsius)
{
  return ((tempCelsius * 9 / 5) + 32);
}



void printData()
{
  //Serial.print("Temperature = ");
  //Serial.print(tempBMP180);
  //Serial.println(" *C");
  
  Serial.print("Pressure = ");
  Serial.print(pressure);
  Serial.println(" Pa");
  
  // Calculate altitude assuming 'standard' barometric
  // pressure of 1013.25 millibar = 101325 Pascal
  Serial.print("Altitude = ");
  Serial.print(altitude);
  Serial.println(" meters");

  Serial.print("Pressure at sealevel (calculated) = ");
  Serial.print(seaLevelPressure);
  Serial.println(" Pa");

  // you can get a more precise measurement of altitude
  // if you know the current sea level pressure which will
  // vary with weather and such. If it is 1015 millibars
  // that is equal to 101500 Pascals.
  Serial.print("Real altitude = ");
  Serial.print(realAltitude);
  Serial.println(" meters");
  
  Serial.print("Humidity: ");
  Serial.print(hum);
  //Serial.println(" %");
  //Serial.print(" %, Temp: ");
  //Serial.print(" %");
  //Serial.print(tempDHT22);
  //Serial.println(" ° Celsius");
  //Serial.println(" Celsius");

  Serial.print("Average Temp: ");
  if (temperatureUnitCelsius)
  {
    Serial.print(averageTemperature);
    Serial.print(" ");
    Serial.print((char)176);    //Degree symbol
    Serial.println("C");
  }
  else
  {
    Serial.print(Convert_CelsiusToFahrenheit(averageTemperature));
    Serial.print(" ");
    Serial.print((char)176);    //Degree symbol
    Serial.println("F");
  }
  
  Serial.println();
}



void draw(void) {
  // graphic commands to redraw the complete screen should be placed here  
  u8g.setFont(u8g_font_unifont);
  //u8g.setFont(u8g_font_osb21);
  u8g.drawStr( 5, 22, "Hello World!");
}

from y experience you cannot connect your device(sensor etc) with different pin, if u are using pin A4 and A5. just use that pin.. make a bus if u want to connect more devices.. use breadboard.. plug a wire to sda and scl ( pin A4 & A5 ) to the breadboard and connect all your i2c device there.. it should be ok!

cheers

Nonsense.

These pins are the same, the I2C pins next to AREF have been added so the newer UNOs and other boards can share the same shields.
They are simply connected to the A4 and A5 pins.

@kbdev:

Did you do your initial tests with both devices connected, or did you test them one by one ?
Also, some of the pinout diagrams available, show the I2C pins incorrect.
This photo from this thread by Nick Gammon (click !) is correct:

ArduinoUno_R3_Pinouts.png

Are you sure it is a SH1106 and not a SH1306 display ?
They will work with the same code, but one will display with an offset of some pixels if controlled by code for the other one.
I have a set of 1306 displays, and both are missing a correct reset circuitry.
If the reset is too short, it will only do a partial reset.
That results in exactly the problem you described: Just some noise is visible.
You can control the noise, and have if scroll horizontally or vertically, but you cannot erase and fill the buffer with the content you like to show.
Of course,that is with my hardware and doesn’t have to be the same with yours.
Can you point to the displays you have ?
Perhaps someone else knows them and knows something specific about those displays from that source.

@kbdev

You need to update the display in a picture loop, e.g. change your code to read:

 if (useOLED)
  {
    u8g.firstPage();  
    do {
      draw();
    } while( u8g.nextPage() );
  }

Clearly you also need to set bool useOLED = true; Then this will print the pressure in mb:

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here 
  u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(5, 22); 
  u8g.print(pressure/100.0);
}

If that does not fix your problem then run an I2C scanner to make sure the devices are visible to the Arduino.

An I2C scanner relies on bidirectional communication. The displays i have came with the return channel disabled. I had to interconnect RX and TX wires from the display on the board it is mounted on for the scanner to work.

This means a scanner might not help you, if the module can't answer, the scanner will go on to the next address and never find the module. This depends on the quality of the module of course.

Also, do not put end resistors to each module. If you would, the resistance would end up too low and cause problems. These problems might not occur on all devices. The displays i use, work fine without end resistor and with a limited cable length.

Thank you for all the replies and feedback. I appreciate it.

@bodmer

Thank you. Changing my code as you suggested solved the problem:

 if (useOLED)
  {
    u8g.firstPage();  
    do {
      draw();
    } while( u8g.nextPage() );
  }

Kind regards and happy development and coding.