OLED fail to initialize with BMP280

Hello,

I'm trying to create a little room temperature sensor with a OLED display.

I'm using a:
Arduino Nano
BMP280
OLED, SD1306

My menu function and push button works fine, but when I try to add the BMP280 to the code, my OLED fails to initialize, and I get the serial print "SSD1306 allocation failed".

As you can see I also tried to add a delay before initializing the BMP280, which didn't do any difference.
I also tried to initialize the BMP280 before the OLED, but this didn't help either.

When I run the below code with all BMP280 stuff commented, the sketch runs fine.
But if I just try to remove the comments for the initializing of the BMP280 I get the error in the serial monitor, and the display is not initializing (the code compiles fine).

I tried running this sketch, LINK, which works fine (with adjusted addresses). So I conclude my BMP and OLED can work together.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Button.h>
//#include <Adafruit_BMP280.h>

// OLED-konfiguration
#define OLED_ADDR 0x3C
#define OLED_RESET 4
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//#define BMP280_I2C_ADDRESS  0x76  // I2C address, Address for BMP280 is usually 0x76 or 0x77
//Adafruit_BMP280 bmp280; // initialize Adafruit BMP280 library

// Buttons pin-no.
#define SELECT_PIN 2
Button upBtn(3); // Pin 3
Button downBtn(5); // Pin 5

// Define default setpoints
float roomSetpoint = 21.0;   // Setpoint for room temperature
float floorSetpoint = 25.0;  // Setpoint for floor temperature
int devAdr = 5;        // Value for RS485 address (1-254)

unsigned long selectPressStart = 0;  // Time the select-btn were pressed
unsigned long buttonHoldTime = 5000; // 5 sec for going to the settings menu
unsigned long lastActivityTime = 0;  // Time for last activity in the menu
unsigned long inactivityTimeout = 60000; // 60 sec timeout for returning to the main menu
bool inMenu = false;                 // State if we are in the main- or settings menu

// For temperature measurement
// Create a BMP280-object

//unsigned long lastTempMeasurement = 0;
//unsigned long tempMeasurementInterval = 5000;  // Temperate measurement every 5 sec
//char tempString[7];   // Buffer for a  en negative temp with one decimal and degree-symbol (°)

byte menuCount = 1; // Actual menupoint

void setup() {
  // Initialize seriel monitor and buttons
  Serial.begin(9600);
  pinMode(SELECT_PIN, INPUT);
  upBtn.begin();
  downBtn.begin();

  // Initialize OLED-display
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println(F("SSD1306 allocation failed"));
    while (true);  // Stops, ifs the display fails
  }

  // Clear display
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 10);
  display.println("OLED OK");
  display.display();
  delay(2000);

// Wait 2 sec before BMP280 initialize
//  delay(2000);  // Wait 2 sec
/*  if (!bmp280.begin(BMP280_I2C_ADDRESS)) {
    //Serial.println("Kunne ikke finde BMP280 sensor!");
    while (1);
  }
*/
/*
  // Setup BMP280
  bmp280.setSampling(Adafruit_BMP280::MODE_NORMAL,     // Measure continuously
                  Adafruit_BMP280::SAMPLING_X2,     // Temperature sampling
                  Adafruit_BMP280::SAMPLING_X16,    // Pressure sampling
                  Adafruit_BMP280::FILTER_X16,      // Filter
                  Adafruit_BMP280::STANDBY_MS_500); // Standby time
*/

}

void loop() {
  // If we are in the settings menu, show settings menu and handle input
  if (inMenu) {
    handleSettingsMenu();
  } else {
  // If we are in the main menu, show main menu and scan for long button press
    displayMainMenu();
    handleMainMenuLongPress();
  }
}

void handleMainMenuLongPress() {
  // Cehck if select-btn is pushed (HIGH)
  if (digitalRead(SELECT_PIN) == HIGH) {
    if (selectPressStart == 0) {
      selectPressStart = millis();  // Start timer, when btn is pushed
      Serial.println("Select button pressed");
    }

    // If select btn is hold for 5 sec
    if (millis() - selectPressStart >= buttonHoldTime) {
      Serial.println("Select button held for 5 seconds, entering Settings menu");
      inMenu = true;  // Go to settings Menu
      selectPressStart = 0;  // Zero timer
      lastActivityTime = millis();  // Start inactivity timeren
      menuCount = 1;  // Clear to Menu point 1, when the menu is accessed
    }
  } else if (selectPressStart != 0) {
    // If Select-btn is released before 5 sec
    Serial.println("Select button released before 5 seconds");
    selectPressStart = 0;  // Zero timeren
  }
}

void displayMainMenu() {
  // Main Menu Screen
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(10, 0);
  display.println("Main");
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(10, 20);
  display.println("T: C");
  display.setCursor(10, 40);
  display.println("H: P");
  display.display();
}

void handleSettingsMenu() {
  // Show Settings menu and handle inputs
  display.clearDisplay();
  // change text display here
  display.setTextSize(2);
  display.setTextColor(WHITE);
  
  display.setCursor(10, 0);
  // menu title
  display.println("Settings");
  //---------------------------------
  display.setTextSize(1);
  // edit menu item 1 here
  display.setCursor(10, 20);
  display.println("Set Rum");
  display.setCursor(80, 20);
  display.println(roomSetpoint);

  // edit menu item 2 here
  display.setCursor(10, 30);
  display.println("Set Gulv");
  display.setCursor(80, 30);
  display.println(floorSetpoint);

  // edit menu item 3 here
  display.setCursor(10, 40);
  display.println("Set Adr");
  display.setCursor(80, 40);
  display.println(devAdr);

  // edit menu item 4 here
  display.setCursor(10, 50);
  display.println("Tilbage");
  display.setCursor(45, 50);


  // Draw marker to show the actual menu point
  display.setCursor(2, (menuCount * 10) + 10);
  display.println(">");

  display.display();

  // Check buttons for activity and zero the inactivity timer
  if (upBtn.pressed()) {
    lastActivityTime = millis();  // Zero inactivity timer
    if (menuCount <= 1)
      menuCount = 4;
    else
      menuCount--; 
  }

  if (downBtn.pressed()) {
    lastActivityTime = millis();  // Zero inactivity timer
	  if (menuCount >= 4)
	    menuCount = 1;
	  else
	    menuCount++;
	}
  
  // When select-btn is pressed short in the menu
  if (digitalRead(SELECT_PIN) == HIGH) {
    Serial.println("Select button pressed in menu");
    lastActivityTime = millis();  // Zero inactivity timer
    executeMenuFunction();  // Execute the chossen function
  }

  // If 60 sec have passed without activity, return to Main Menu
  if (millis() - lastActivityTime >= inactivityTimeout) {
    Serial.println("No activity for 60 seconds, returning to main menu");
    inMenu = false;
  }
}
/*
// Function to update the temperature
void updateTemperature() {
  // Read the temperature from the BMP280
  float temperature = bmp.readTemperature();

  // Convert temperature to a string
  dtostrf(temperature, 4, 1, tempString);  // 4 is the min. width, 1 is the decimals
  strcat(tempString, "\xB0\C");  // add degree sign (°) and "C" to the string

  Serial.print("Display Temp = ");
  Serial.println(tempString);  // Print the Display temp string to the Serial Monitor
}
*/
void executeMenuFunction() {
  switch (menuCount) {
    case 1:
      Serial.println("Executing Set Rum");
      break;
    case 2:
      Serial.println("Executing Set Gulv");
      break;
    case 3:
      Serial.println("Executing Set Adr");
      break;
    case 4:
      Serial.println("Executing Tilbage");
      inMenu = false;  // Return to the main menu
      break;
  }
}
// END

Please, show the picture of the BMP280 Breakout board that you are using.

The Adafruit_SSD1306 library tries to allocate 1K of RAM at runtime. There isn't enough RAM left over for it to do that. That's what the allocation error means.

You can try enclosing any character strings used in print or println with the F() macro to avoid making copies of them in RAM. That would save you over 300 bytes of RAM. That might be enough to get your sketch to run. If it's not, you'd have to investigate an alternate library that doesn't allocate that 1K screen buffer, like SSD1306Ascii. You'd have to rewrite parts of your sketch to accommodate it.

1 Like

Hmm okay.
But how come the other code works then? it also uses 703 bytes, "only" leaving 642 left?

So considering, i'm planning to add more functions to this, I should consider using another microcontroller?

Your response made me shake my head and sigh. I'll leave you to find your own solution then. Good luck with your project.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.