Editorial Solution

We need to connect below three I2C devices to an Arduino UNO (master).

  1. BMP180 sensor: for pressure, temperature, and altitude(3.3 V).
  2. DS1307 RTC: for time and date(5 V).
  3. OLED display: to show the data(3.3V - 5V).

The I2C communication frequency is set to 100 kHz, as all slave devices support this rate.

Voltage Level Compatibility

  • Ensure all devices operate within their voltage level to avoid potential damage. 
  • The diagram below, referenced from the datasheet, illustrates how a voltage level translator can be used to connect devices operating at different voltage levels.
  • The BMP180 has an inbuilt voltage regulator (662k), allowing its SDA and SCL lines to be directly connected to the Arduino Uno without the need for an external voltage level translator
  • Additionally, ensure that the BMP180 sensor module is supplied with a 3.3V voltage.

Hardware Connections

Let's go through the hardware connections step by step:

  1. Connect 5V and GND from the Arduino Uno (master) to the OLED display and RTC module. Connect 3.3V and GND to the BMP180 sensor module.
  2. Connect the SDA and SCL pins of all devices.
  3. We are going to use internal pull-up resistors for the SDA and SCL connections.
  4. Ensure that the GND of all devices is connected to a common ground.

Note: When connecting multiple devices, ensure that the total current draw does not exceed the controller's maximum sourcing or sinking capability to avoid overloading.

Circuit Diagram

Firmware

  • We will read the time and date from the RTC DS1307 and air pressuretemperature, and altitude data from the BMP180 sensor module and display them on the OLED display.
  • We used Adafruit's SSD1306 library (available on GitHub) for the OLED, Adafruit_BMP085.h for the BMP180 sensor module, and RTClib.h by Adafruit for the RTC DS1307.
  • For instructions on how to add a custom library to the Arduino IDE, refer to Adding Library to Arduino IDE.

Note: Adafruit_BMP085.h can be used for both the BMP085 and BMP180 Barometric Pressure sensor breakout boards.

Master Code

#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_BMP085.h>

#define oled_address 0x3C  // Define the I2C address of the OLED display

// Create an object to interface with the RTC module
RTC_DS1307 rtc;

// Create an object to interface with the BMP180 sensor
Adafruit_BMP085 bmp;

// Create an  object for OLED display (128x64 size)
#define SCREEN_WIDTH 128                                                   // Width of the display in pixels
#define SCREEN_HEIGHT 64                                                   // Height of the display in pixels
#define OLED_RESET -1                                                      // Define the reset pin for the OLED (not used in this case)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);  // Initialize OLED display object


void setup() {

  Serial.begin(115200);

  // Initialize BMP180 sensor
  Serial.print("BMP180 sensor initializing...");

  // Wait until BMP180 sensor is initialized
  while (!bmp.begin()) {
    Serial.print(" .");
    delay(100);
  }
  Serial.println(" ");
  Serial.println("BMP180 sensor initialization complete.");

  // Check RTC DS1307 is successfully connected or not
  Serial.print("RTC Device scanning...");

  // Wait until RTC DS1307 is not found
  while (!rtc.begin()) {
    Serial.print(" .");
    delay(100);
  }
  Serial.println(" ");
  Serial.println("RTC device found");

  // Check if the OLED display is connected
  Serial.print("OLED display scanning...");
  Wire.beginTransmission(oled_address);  // Start I2C communication with OLED
  while (Wire.endTransmission()) {       // Check if the OLED responds
    Serial.print(".");
    delay(100);
  }
  Serial.println(" ");
  Serial.println("OLED display found");

  // Initialize OLED display
  Serial.print("OLED display initializing.....");

  // Initialize OLED display
  while (!display.begin(SSD1306_SWITCHCAPVCC, oled_address)) {
    Serial.print(" .");
    delay(100);
  }
  Serial.println(" ");
  Serial.println("OLED display initialization complete.");

  delay(2000);  // Pause for 2 seconds after the initial setup

  // Clear the display and set up text parameters
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);  // Set text color to white
  // Uncomment the line below to set time on RTC initially (if needed)
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //Initialize the RTC with the compile-time date and time
}

void loop() {

  // Get the current time and date from RTC
  DateTime now = rtc.now();

  // Clear the display and start updating it
  display.clearDisplay();
  display.setCursor(0, 0);  //Set the cursor to the top-left corner (column 0, row 0) of the OLED display

  // display date top-left corner (Date/Month/Year)
  display.print(now.day(), DEC); 
  display.print("/");
  display.print(now.month(), DEC);  
  display.print("/");
  display.print(now.year(), DEC);  
  
  display.setCursor(71, 0);  //Set the cursor to the top-left corner (column 71, row 0) of the OLED display
 
  // Display the current time(dec value) on top-right corner (hours:minutes:seconds)
  display.print(now.hour(), DEC);  
  display.print(':');
  if (now.minute() < 10) {  // Add leading zero for minutes less than 10
    display.print('0');
  }
  display.print(now.minute(), DEC);  
  display.print(':');

  if (now.second() < 10) {  // Add leading zero for seconds less than 10
    display.print('0');
  }
  display.print(now.second(), DEC);  

  // Display atmospheric pressure value from BMP180 sensor (Unit = "Pa")
  display.setCursor(0, 16);  // Set the cursor to the (column 0, row 16) of the OLED display
  display.print("Pressure = ");
  display.print(bmp.readPressure());  // Read and display pressure in Pascals
  display.print(" Pa");
  
   // Display temperature value from BMP180 sensor(degree celcius(°C))
  display.setCursor(0, 32);  // Set the cursor to the (column 0, row 32) of the OLED display
  display.print("Temp = ");
  display.print(bmp.readTemperature());
  display.print(" ");
  display.write(248);
  display.print("C");
   
  // Calculate altitude(meter) assuming 'standard' barometric
  // pressure of 1013.25 millibar = 101325 Pascal
  display.setCursor(0, 48);  // Set the cursor to the (column 0, row 48) of the OLED display
  display.print("Altitude = ");
  display.print(bmp.readAltitude());
  display.print(" m");
  
  display.display();  // Update the OLED display with the new content

  // Wait for 1 second before updating again
  delay(1000);
}


Code Explanation

  • rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    • __DATE__ and __TIME__ are predefined macros in Arduino that represent the compile date and time of the code.
    • These values are based on the time when the code was compiled, not when it was uploaded.
    • rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); sets the RTC to the time and date of the sketch compilation.
    • You can manually set the time with rtc.adjust(DateTime(2025, 1, 16, 12, 0, 0));// to set the RTC to a specific date and time.
  •  DateTime now = rtc.now();
    • Reads the current date and time from the RTC module. The now object stores the current time and date (hour, minute, second, day, month, and year).
  •  bmp.readPressure();
    • Reads the pressure value from the BMP180 sensor in Pascals (Pa).
  • bmp.readAltitude();
    • Reads the altitude value from the BMP180 sensor in meters (m).
  • bmp.readTemperature();  
    • Reads the temperature value from the BMP180 sensor in degrees Celsius (°C).
  • display.display();
    • Updates the OLED display to show the latest information (time and pressure).

OUTPUT

Hardware Setup

Video


 

 

 

 

 

 

 

Submit Your Solution