SSD1306 Not working after 20600 bytes of memory is used

My program will run but after the program size is above around 21,000 bytes to SPI SSDE1306 stops connecting. The rest of the program works but it fails to connect to the OLED Display.
The instant I remove some of my code it starts working again (I tried a few different sections and all had the same result)
Just wondering if anyone else has had this issue?

Using Atmega328P-PU
Thanks in advance.

//Oled Setup
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);


//GPS Setup
#include <SoftwareSerial.h>
// Connect the GPS RX/TX to arduino pins 3 and 5
SoftwareSerial serial = SoftwareSerial(3,5);

const unsigned char UBX_HEADER[] = { 0xB5, 0x62 };

const char UBLOX_INIT[] PROGMEM = {
  // Disable NMEA
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, // GxGGA off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, // GxGLL off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, // GxGSA off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, // GxGSV off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, // GxRMC off
  0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, // GxVTG off

  // Disable UBX
  0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, //NAV-PVT off
  0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, //NAV-POSLLH off
  0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, //NAV-STATUS off

  // Enable UBX
  0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x01,0x00,0x00,0x00,0x00,0x18,0xE1, //NAV-PVT on

  // Rate
  0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz)
};

struct NAV_PVT {
  unsigned char cls;
  unsigned char id;
  unsigned short len;
  unsigned long iTOW;          // GPS time of week of the navigation epoch (ms)
  
  unsigned short year;         // Year (UTC) 
  unsigned char month;         // Month, range 1..12 (UTC)
  unsigned char day;           // Day of month, range 1..31 (UTC)
  unsigned char hour;          // Hour of day, range 0..23 (UTC)
  unsigned char minute;        // Minute of hour, range 0..59 (UTC)
  unsigned char second;        // Seconds of minute, range 0..60 (UTC)
  char valid;                  // Validity Flags (see graphic below)
  unsigned long tAcc;          // Time accuracy estimate (UTC) (ns)
  long nano;                   // Fraction of second, range -1e9 .. 1e9 (UTC) (ns)
  unsigned char fixType;       // GNSSfix Type, range 0..5
  char flags;                  // Fix Status Flags
  unsigned char reserved1;     // reserved
  unsigned char numSV;         // Number of satellites used in Nav Solution
  
  long lon;                    // Longitude (deg)
  long lat;                    // Latitude (deg)
  long height;                 // Height above Ellipsoid (mm)
  long hMSL;                   // Height above mean sea level (mm)
  unsigned long hAcc;          // Horizontal Accuracy Estimate (mm)
  unsigned long vAcc;          // Vertical Accuracy Estimate (mm)
  
  long velN;                   // NED north velocity (mm/s)
  long velE;                   // NED east velocity (mm/s)
  long velD;                   // NED down velocity (mm/s)
  long gSpeed;                 // Ground Speed (2-D) (mm/s)
  long heading;                // Heading of motion 2-D (deg)
  unsigned long sAcc;          // Speed Accuracy Estimate
  unsigned long headingAcc;    // Heading Accuracy Estimate
  unsigned short pDOP;         // Position dilution of precision
  short reserved2;             // Reserved
  unsigned long reserved3;     // Reserved
};

NAV_PVT pvt;

void calcChecksum(unsigned char* CK) {
  memset(CK, 0, 2);
  for (int i = 0; i < (int)sizeof(NAV_PVT); i++) {
    CK[0] += ((unsigned char*)(&pvt))[i];
    CK[1] += CK[0];
  }
}

bool processGPS() {
  static int fpos = 0;
  static unsigned char checksum[2];
  const int payloadSize = sizeof(NAV_PVT);

  while ( serial.available() ) {
    byte c = serial.read();
    if ( fpos < 2 ) {
      if ( c == UBX_HEADER[fpos] )
        fpos++;
      else
        fpos = 0;
    }
    else {      
      if ( (fpos-2) < payloadSize )
        ((unsigned char*)(&pvt))[fpos-2] = c;

      fpos++;

      if ( fpos == (payloadSize+2) ) {
        calcChecksum(checksum);
      }
      else if ( fpos == (payloadSize+3) ) {
        if ( c != checksum[0] )
          fpos = 0;
      }
      else if ( fpos == (payloadSize+4) ) {
        fpos = 0;
        if ( c == checksum[1] ) {
          return true;
        }
      }
      else if ( fpos > (payloadSize+4) ) {
        fpos = 0;
      }
    }
  }
  return false;
}


//in cartemp Setup
#include <dht11.h>
#define DHT11PIN 11
dht11 DHT11;

//Genral Verables
const int buttonPin = 10;
const int buttonPin2 = 9;
int count = 0;
long temp = 0;
long times = 0;
long times2 = 0;
float times3 = 0;
int go = 0;
int buttonState = 0;
int buttonState2 = 0;
const int xpin = 3;
float gmeter = 0;

//water temp setup
#include <math.h>
double Thermistor(int RawADC) 
{
 int Temp;
 Temp = log(10000.0*((1024.0/RawADC-1)));
 Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
 Temp = Temp - 273.15; 
 return Temp;
}


void setup() 
{

  Serial.begin(115200);
  serial.begin(9600);
  
  // Start Screen
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) 
  {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }  
    delay(100);
    display.clearDisplay();
    display.setTextSize(3);                    
    display.setTextColor(WHITE);         
    display.setCursor(10,10);        
    display.print("TOYOTA");
    display.display();
    delay(300);
    display.setTextSize(1);                    
    display.setTextColor(WHITE);         
    display.setCursor(45,40);        
    display.print("Starlet");
    display.display();
    delay(1500);
    
  //Start GPS
  for(int i = 0; i < sizeof(UBLOX_INIT); i++) 
  {                        
    serial.write( pgm_read_byte(UBLOX_INIT+i) );
    delay(5); // simulating a 38400baud pace (or less), otherwise commands are not accepted by the device.
  }
  pinMode(buttonPin, INPUT);
  pinMode(buttonPin2, INPUT);

}

void loop() 
{
  buttonState = digitalRead(buttonPin);
  buttonState2 = digitalRead(buttonPin2);
  if (buttonState == HIGH)
  {
    count = count + 1;
    delay(300);
  }
  if (count == 0)
    {
    if ( processGPS() ) 
    {
      display.setTextSize(3);
      display.setTextColor(WHITE);
      display.clearDisplay();
      display.setCursor(30, 15);
      display.println((times3/1000));
      display.setTextSize(1);
      display.setCursor(85, 15);
      display.println("Time");
      display.setCursor(50, 50);
      display.println((pvt.gSpeed/1000.0f)*3.6);
      display.setCursor(85, 50);
      display.println("KPH");
      display.display();
        if ((pvt.gSpeed/1000.0f)*3.6 > 4 && go == 0)
        {
          times = millis();
          go = 1;
        }
        if ((pvt.gSpeed/1000.0f)*3.6 > 100 && go == 1)
        {
          times2 = millis();
          times3 = (times2 - times);
          go = 2;
        }
      if (buttonState2 == HIGH) 
      {
        go = 0;
        times3 = 0;
      }
    }
  }
  if (count == 1)
  {
    int chk = DHT11.read(DHT11PIN);
    display.clearDisplay();
    display.setTextSize(3);
    display.setTextColor(WHITE);
    display.setCursor(50, 15);
    display.println((float)DHT11.temperature, 0);
    display.setTextSize(1);
    display.setCursor(30, 40);
    display.println("In Car Temp");
    display.display();
  }
  if (count == 2)
  {
      display.setTextSize(3);
      display.setTextColor(WHITE);
      display.clearDisplay();
      display.setCursor(30, 15);
      display.println((pvt.gSpeed/1000.0f)*3.6, 0);
      display.setTextSize(1);
      display.setCursor(85, 15);
      display.println("KPH");
      display.display();
  }
  if (count == 3)
  {
    int x = analogRead(xpin);
    gmeter= (((float)x - 331.5)/65*9.8);
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.clearDisplay();
    display.setCursor(10, 10);
       if (gmeter >= -1.5 && gmeter <= 3.5)
    {
      display.println("    |");
    }
    if (gmeter > 3.5 && gmeter <= 5.5)
    {
      display.println("    ||");
    }
        if (gmeter > 5.5 && gmeter <= 7.5)
    {
      display.println("    |||");
    }
        if (gmeter > 7.5 && gmeter <= 9.5)
    {
      display.println("    ||||");
    }
        if (gmeter > 9.5)
    {
      display.println("    |||||");
    }

    
    if (gmeter < -2.5 && gmeter >= -4.5)
    {
      display.println("   ||");
    }
        if (gmeter < -4.5 && gmeter >= -6.5)
    {
      display.println("  |||");
    }
        if (gmeter < -6.5 && gmeter >= 8.5)
    {
      display.println(" ||||");
    }
        if (gmeter < -8.5)
    {
      display.println("|||||");
    }
    display.setCursor(25, 40);
    display.println("G-force");
    display.display();
  }
  if (count == 4)
  {
    display.clearDisplay();
    display.setTextSize(3);
    display.setTextColor(WHITE);
    display.setCursor(40, 0);
    display.println(int(Thermistor(analogRead(0))));
    display.setTextSize(1);
    display.setCursor(15, 40);
    display.println("Water temperature");
    display.display();
  }
 if (count == 5)
  {
    count = 0;
  }
}

How much dynamic memory (ram) does the compiler show being used? The display needs 1024 bytes for a buffer, and that is allocated at run time so is not shown in the total from the compiler.

1 Like

"Sketch uses 20554 bytes (63%) of program storage space. Maximum is 32256 bytes.
Global variables use 872 bytes (42%) of dynamic memory, leaving 1176 bytes for local variables. Maximum is 2048 bytes."

Does the display take up that much of the ram?

The 128x64 OLED display takes 1024 bytes of ram, which the Adafruit library allocates at run-time. There are other libraries, such as the u8g2 library, that have an option for a smaller buffer, or no buffer if you can restrict the output to fixed-size, text-only display.

1 Like

Thank you so much man, would have taken ages for me to figure that out alone!

The u8x8 Library has worked perfectly!

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