Problem with OLED libraries and SD library

Hi everyone

I want to measure a data and display that on the OLED 128*64. I also want to Write/Read data on/from SD card.

When I just measure and display the data on OLED, it works perfectly. But the problem is that when I add the Sd library and also the code of SD, the code stick in the following code and the serial monitor shows "SSD1306 allocation failed".

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }

should I change any line in the libraries of OLED or SD?

The following is the code I've used:

//OLED Screen
#include <SPI.h>
#include <SD.h> //Load SD card library
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// SD Card reader Setting
int SDSelect = 5; //chipSelect pin for the SD card Reader
File TempData; //Data object you will write your sesnor data to

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16

byte CommandPin = 2;
byte GraphPin = 3;
bool Redraw1 = true;

//Sensor
unsigned char Re_buf[11], counter = 0;
unsigned char sign = 0;
float TO = 0, TA = 0;


void setup() {
  pinMode(CommandPin, INPUT);
  digitalWrite(CommandPin, LOW);
  pinMode(GraphPin, INPUT);
  digitalWrite(GraphPin, LOW);
  Serial.begin(115200);
  
  // SD Card
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print("Initializing SD card...");

  if (!SD.begin(SDSelect)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }
  display.fillScreen(0);
  // Clear the buffer
  display.clearDisplay();

  Serial.write(0XA5);
  Serial.write(0X45);
  Serial.write(0XEA);

}

void loop() {
  if (!digitalRead(CommandPin) & digitalRead(GraphPin)) {// Measuring the temps
    unsigned char i = 0, sum = 0;
    if (sign) {
      sign = 0;
      for (i = 0; i < 8; i++)
        sum += Re_buf[i];
      if (sum == Re_buf[i] ) {
        TO = (float)(Re_buf[4] << 8 | Re_buf[5]) / 100;
        TA = (float)(Re_buf[6] << 8 | Re_buf[7]) / 100;
        ShowTemp(TA, TO);
      }
    }
  }
  if(!digitalRead(GraphPin) & digitalRead(CommandPin)){// Storing the temps in a file on sd
    TempData = SD.open("Temp.txt", FILE_WRITE);
    if(TempData){
      Serial.print("Writing to SD");
      TempData.println(TO);
      TempData.close();
    }
  }
}

void serialEvent() {
  while (Serial.available()) {
    Re_buf[counter] = (unsigned char)Serial.read();
    if (counter == 0 && Re_buf[0] != 0x5A) return;
    counter++;
    if (counter == 9)
    {
      counter = 0;
      sign = 1;
    }
  }
}

void ShowTemp(float TA, float TO) {
  display.clearDisplay();

  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print(F("TA: "));
  display.println(TA);
  display.print(F("TO: "));
  display.print(TO);
  display.display();
  delay(100);
}

Any help is appreciated.
Thanks

Show ALL your code as stated in How to use the forum :slight_smile: Otherwise you're better off at the neighbors.

In the old days the 128x64 pixel buffer was allocated globally by Adafruit_SSD1306. So the build report would show that 1024 bytes of SRAM were being used.
The SD library requires some SRAM too.

A Uno only has 2048 bytes of SRAM. You need an Arduino with more SRAM if you want to use a full 128x64 buffer e.g. Adafruit_SSD1306

Make sure that all anonimous strings are in Flash. Make sure that you are careful with your variables to minimise the SRAM use.

Alternatively use U8g2lib which can work with tiny SRAM buffer. Or U8x8.

This all sounds a bit technical. Please post your code. Then we can give a simpler answer.

David.

septillion:
Show ALL your code as stated in How to use the forum :slight_smile: Otherwise you're better off at [http://snippets-r-us.com/]the neighbors[/url].

The post is updated.

I built your sketch for a Uno:

Using library SPI at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\SPI 
Using library SD at version 1.2.3 in folder: C:\Program Files\Arduino-1.8.8\libraries\SD 
Using library Wire at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\Wire 
Using library Adafruit_GFX_Library at version 1.4.8 in folder: C:\Users\David\Documents\Arduino\libraries\Adafruit_GFX_Library 
Using library Adafruit_SSD1306 at version 1.2.9 in folder: C:\Users\David\Documents\Arduino\libraries\Adafruit_SSD1306 
"C:\\Users\\David\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-size" -A "C:\\Users\\David\\AppData\\Local\\Temp\\arduino_build_138677/Mahdiyar_SD.ino.elf"
Sketch uses 24314 bytes (75%) of program storage space. Maximum is 32256 bytes.
Global variables use 1320 bytes (64%) of dynamic memory, leaving 728 bytes for local variables. Maximum is 2048 bytes.

Note that you only have 728 bytes for local variables. There is not enough to allocate 1024 bytes for a 128x64 display.

As a typical SD sketch, I built the ReadWrite.ino from the <SD.h> examples

Using library SPI at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\SPI 
Using library SD at version 1.2.3 in folder: C:\Program Files\Arduino-1.8.8\libraries\SD 
"C:\\Users\\David\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-size" -A "C:\\Users\\David\\AppData\\Local\\Temp\\arduino_build_469955/ReadWrite.ino.elf"
Sketch uses 10912 bytes (33%) of program storage space. Maximum is 32256 bytes.
Global variables use 1008 bytes (49%) of dynamic memory, leaving 1040 bytes for local variables. Maximum is 2048 bytes.

Either use U8g2lib library or buy a "bigger" Arduino.

David.

david_prentice:
I built your sketch for a Uno:

Using library SPI at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\SPI 

Using library SD at version 1.2.3 in folder: C:\Program Files\Arduino-1.8.8\libraries\SD
Using library Wire at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\Wire
Using library Adafruit_GFX_Library at version 1.4.8 in folder: C:\Users\David\Documents\Arduino\libraries\Adafruit_GFX_Library
Using library Adafruit_SSD1306 at version 1.2.9 in folder: C:\Users\David\Documents\Arduino\libraries\Adafruit_SSD1306
"C:\Users\David\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\5.4.0-atmel3.6.1-arduino2/bin/avr-size" -A "C:\Users\David\AppData\Local\Temp\arduino_build_138677/Mahdiyar_SD.ino.elf"
Sketch uses 24314 bytes (75%) of program storage space. Maximum is 32256 bytes.
Global variables use 1320 bytes (64%) of dynamic memory, leaving 728 bytes for local variables. Maximum is 2048 bytes.



Note that you only have 728 bytes for local variables. There is not enough to allocate 1024 bytes for a 128x64 display.

As a typical SD sketch, I built the ReadWrite.ino from the <SD.h> examples


Using library SPI at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\SPI
Using library SD at version 1.2.3 in folder: C:\Program Files\Arduino-1.8.8\libraries\SD
"C:\Users\David\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\5.4.0-atmel3.6.1-arduino2/bin/avr-size" -A "C:\Users\David\AppData\Local\Temp\arduino_build_469955/ReadWrite.ino.elf"
Sketch uses 10912 bytes (33%) of program storage space. Maximum is 32256 bytes.
Global variables use 1008 bytes (49%) of dynamic memory, leaving 1040 bytes for local variables. Maximum is 2048 bytes.




Either use U8g2lib library or buy a "bigger" Arduino.

David.

thatk you for your reply. But as I mentioned I have not problem with OLED 128*64 and it works alone perfectly. The problem is when I add SD card.

First question: Are you using a Uno ?

In the old days, an Adafruit_SSD1306 would use a 1024 byte buffer at compile time.
Nowadays, they allocate at run time e.g. the ssd1306_128x64_i2c.ino example

Using library SPI at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\SPI 
Using library Wire at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\Wire 
Using library Adafruit_GFX_Library at version 1.4.8 in folder: C:\Users\David\Documents\Arduino\libraries\Adafruit_GFX_Library 
Using library Adafruit_SSD1306 at version 1.2.9 in folder: C:\Users\David\Documents\Arduino\libraries\Adafruit_SSD1306 
"C:\\Users\\David\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-size" -A "C:\\Users\\David\\AppData\\Local\\Temp\\arduino_build_113163/ssd1306_128x64_i2c.ino.elf"
Sketch uses 20718 bytes (64%) of program storage space. Maximum is 32256 bytes.
Global variables use 519 bytes (25%) of dynamic memory, leaving 1529 bytes for local variables. Maximum is 2048 bytes.

By the time that you allocate 1024 bytes from the heap, you have got 505 bytes left. You have no hope of running SD as well.
Actually, allocating from the heap probably uses a few extra housekeeping bytes.

David.

david_prentice:
First question: Are you using a Uno ?

In the old days, an Adafruit_SSD1306 would use a 1024 byte buffer at compile time.
Nowadays, they allocate at run time e.g. the ssd1306_128x64_i2c.ino example

Using library SPI at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\SPI 

Using library Wire at version 1.0 in folder: C:\Program Files\Arduino-1.8.8\hardware\arduino\avr\libraries\Wire
Using library Adafruit_GFX_Library at version 1.4.8 in folder: C:\Users\David\Documents\Arduino\libraries\Adafruit_GFX_Library
Using library Adafruit_SSD1306 at version 1.2.9 in folder: C:\Users\David\Documents\Arduino\libraries\Adafruit_SSD1306
"C:\Users\David\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\5.4.0-atmel3.6.1-arduino2/bin/avr-size" -A "C:\Users\David\AppData\Local\Temp\arduino_build_113163/ssd1306_128x64_i2c.ino.elf"
Sketch uses 20718 bytes (64%) of program storage space. Maximum is 32256 bytes.
Global variables use 519 bytes (25%) of dynamic memory, leaving 1529 bytes for local variables. Maximum is 2048 bytes.




By the time that you allocate 1024 bytes from the heap, you have got 505 bytes left. You have no hope of running SD as well.
Actually, allocating from the heap probably uses a few extra housekeeping bytes.

David.

Yes I use Arduino Uno, in which ATMEGA328p-PU is utilized. As I Mentioned, I checked both OLED 128*64 and SD module separately and they work fine. for more explanation, it can be uploaded on uno and I get no error but I take no result since the code stick in the following loop. (Check the code in the main post)

while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

Have you heard the expression ? "You can not fit a quart into a pint pot"

If English is not your first language, please say so.

A quart is an obsolete measure used by backward countries like the U.S.

David.

Or to recap, I can fit a gallon of gasoline in my 5 liter jerrycan. I can also fit a gallon of diesel in my 5 liter jerrycan. But if I try to do that at the same time I definitely overflow it!

1 Like

david_prentice:
Have you heard the expression ? "You can not fit a quart into a pint pot"

If English is not your first language, please say so.

A quart is an obsolete measure used by backward countries like the U.S.

David.

thank you so much for your reply. I totally understand what you said. I think that if the amount of memory is the point, the code should have not uploaded on UNO. While I upload the code successfully.

If I understand you correctly, it may happen even after uploading process. Please tell me if I'm wrong.

Many thanks.

Mahdiyar:
If I understand you correctly, it may happen even after uploading process. Please tell me if I'm wrong.

Correct! Trouble is, memory management on a micro controller is pretty basic. But even if it can see it has no more memory it has no way of telling you.

And why doesn't it fail to upload? That's because there is a difference between globals defined during compiling and variables defined during runtime. Ever notice the compiler message?

Global variables use 488 bytes (23%) of dynamic memory, leaving 1560 bytes for local variables. Maximum is 2048 bytes.

It's quite impossible to know what variables you want to make during runtime because it would have to know every possible execution flow. For all the compiler knows, you might want a new variable every time you press a button. Or you might do all kinds of String (with a capital!) magic. Will eat your memory on runtime and probably leaves you with Swiss cheese for memory.

septillion:
Correct! Trouble is, memory management on a micro controller is pretty basic. But even if it can see it has no more memory it has no way of telling you.

And why doesn't it fail to upload? That's because there is a difference between globals defined during compiling and variables defined during runtime. Ever notice the compiler message?It's quite impossible to know what variables you want to make during runtime because it would have to know every possible execution flow. For all the compiler knows, you might want a new variable every time you press a button. Or you might do all kinds of String (with a capital!) magic. Will eat your memory on runtime and probably leaves you with Swiss cheese for memory.

thank you so much for your explanation.