Do I just need a board with more RAM? SRAM issues

I’m brand new to Arduino.

Here are my project parts:
SparkFun RedBoard Qwiic (ATmega328)
SAM-M8Q (Qwiic) GPS Breakout
Zio Qwiic OLED Display (1.5inch, 128x128)

Goal:
Create a “Sensor Box” to display various sensor readings on the OLED display. GPS info, Temp and Humidity, etc.

Current problem:
When I try to add additional sensor outputs to the OLED display, the display stops showing live data. I tiried adding the temperature output from a DHT11, and all of the “dynamically updated” GPS info just stopped showing up on the OLED.

Suspected cause:
Running out of memory

Solutions I have considered:

  • Using the F() string shortcut - I can’t figure out how to make this work. Do I need to add an Include statement? Also, all the examples I see of for the F() are in Serial.println - I’m not using serial
  • Using something else besides String - I tried to use byte for MPH and Number of Sats, but it didn’t seem to make a difference.

Where I need help:

  • Do I just need a board with more SRAM to solve this problem?
  • Is there something I’m doing in my code that is wasting SRAM?
  • Am I even on the right track? Could my problem be something else?

Other thoughts:
I believe the libraries are taking up the most SRAM. If I’m just using basic functionality, is there a smaller Library I can use?

#include <SparkFun_Ublox_Arduino_Library.h>
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1327_MIDAS_128X128_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); /* Uno: A4=SDA, A5=SCL, add "u8g2.setBusClock(400000);" into setup() for speedup if possible */
SFE_UBLOX_GPS myGPS;

void setup(void) {
  u8g2.begin();
}


void loop(void) {
  if (myGPS.begin() == false) {
    myGPS.setI2COutput(COM_TYPE_UBX);
    myGPS.saveConfiguration();
  }

  float latitude = myGPS.getLatitude();
  latitude = latitude / 10000000;

  float longitude = myGPS.getLongitude();
  longitude = longitude / 10000000;

  int speedMMperS = myGPS.getGroundSpeed();
  float speedMPH = speedMMperS / 447.00;

  int8_t numSats = myGPS.getSIV();
  
  
  
  //Convert to Strings For Display on OLED
  String strLat = String(latitude, 6);
  String strLong = String(longitude, 6);
  String strMPH = String(speedMPH, 1);
  String strSATS = String(numSats);
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB10_tr);
    u8g2.drawStr(0, 15, "LAT: ");
    u8g2.drawStr(42, 15, strLat.c_str());
    u8g2.drawStr(0, 30, "LON: ");
    u8g2.drawStr(42, 30, strLong.c_str());
    u8g2.drawStr(0, 45, "MPH: ");
    u8g2.drawStr(42, 45, strMPH.c_str());
    u8g2.drawStr(0, 60, "SATS: ");
    u8g2.drawStr(48, 60, strSATS.c_str());

  } while ( u8g2.nextPage() );
  delay(1000);
}

Thank you in advance for the help! I have read and searched over the forum before posting, which is where I got the suggestions above. But, before I go buy a new board with more RAM, I want to be sure my thought process is correct!

If you are running out of memory, you should be getting advice on that when compiling. It’s usually conservative because there may be overheads used when running that can’t be forseen, so it’s advice that really should be taken seriously, and tinkering around the edges is usually just putting off the inevitable until next week - that’s the time when you want to add something you didn’t think of this week.

The most obvious signs of how close to the wind you are sailing are in the size and number of your libraries. I know nothing about Arduino.h, don’t have it, and have never needed it. The call to use it may simply be redundant, but I think you are using archaic code and should seriously question it. If you are just printing text, you might be better off using Adafruit libaries. I don’t know how much you save by doing that. They are the only OLED libraries I have ever used.

I can’t comment much on the code although I submit that

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

while probably not too expensive, is indeed absurd. If you can’t make up your mind whether you are holding an SPI or I2C device in your hand, and write the code accordingly, you deserve the grief you are getting.

I hope no one on this forum suggested that you use Strings, because they eat up RAM, causing malfunctions and program crashes. It is [u]never[/u] necessary to use Strings.

Also, all of the character constants are put into RAM by default, so you need to learn about using PROGMEM and the F() macro.

   u8g2.drawStr(0, 15, "LAT: ");

Nick_Pyner: If you are running out of memory, you should be getting advice...

Thanks for the response. I have removed the Arduino library and the if statements on the includes. Just FYI, I copy/pasted a lot of the code which is why all of that stuff was included. Like I mentioned, I'm pretty new to all of this.

I will take a look at the Adafruit libraries.

Here is the error/warning I get during compiling:

Sketch uses 25278 bytes (78%) of program storage space. Maximum is 32256 bytes.
Global variables use 1676 bytes (81%) of dynamic memory, leaving 372 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.

The questions I am trying to answer are: 1) Are the code optimizations I can perform enough to let me do what I want to do? 2) What exactly are the code optimizations I can do?

Thanks!

What you posted is the warning I was talking about. The 78% sounds pretty reasonable, so was it an improvement on what you had before?

I don't want to comment on the code, but this looks very smelly to me.

  float latitude = myGPS.getLatitude();
  latitude = latitude / 10000000;

I understand floats take up memory, but I simply take the view that, if you want a float, you use float. Now, I don't know anything about using GPS, but I don't understand why you would divide a float by such a number, and I bet it isn't kosher.

I did write a GPS ‘checker’ program that displays lat,lon,alt,sats,hdop,time,date on one of the 128x64 OLEDs; it’s memory consumption was;

Sketch uses 14856 bytes (46%) of program storage space. Maximum is 32256 bytes.
Global variables use 921 bytes (44%) of dynamic memory, leaving 1127 bytes for local variables. Maximum is 2048 bytes.

I used U8x8lib.h though and TinyGPS.

Do you need to use the graphics driver for the OLED if your only displaying text.

I used TinyGPS++ for the GPS.

Edit: I have attached the program.

29_GPS_Checker_With_Display.ino (9.51 KB)

Clearly 14856 bytes (46%) can't be a problem. What I was asking about is the compiler feedback when you thought you did have a problem, and was it more than 78%.

If you are using text, you certainly don't need the graphics library, hence my comment. I don't know how much difference this approach makes as it is the only library for OLED I have succesfully used, but I assume it will work on yours and it should help.

Nick_Pyner: Clearly 14856 bytes (46%) can't be a problem. What I was asking about is the compiler feedback when you thought you did have a problem, and was it more than 78%.

Nick, the 46% was srnet's code, not the OP's code.

Nick_Pyner: If you are using text, you certainly don't need the graphics library, hence my comment. I don't know how much difference this approach makes as it is the only library for OLED I have succesfully used, but I assume it will work on yours and it should help.

The graphics object (u8g2) will be using more ram than the text only object (u8x8), but not that much more. The constructor, U8G2_SSD1327_MIDAS_128X128_1_HW_I2C, only reserves a 128 byte buffer, and that probably happens at run-time so won't show in the compiler estimate, I suspect.

When I read the OP, my immediate thought was that the OP might be using the constructor U8G2_SSD1327_MIDAS_128X128_F_HW_I2C, which would reserve a 1.5K byte buffer, which would certainly have explained the memory problems! But it's not that.

Nick_Pyner: I know nothing about Arduino.h, don't have it, and have never needed it.

I believe that is one of the standard parts of the Arduino system and you probably use it all the time without realising it.

...R

Robin2: I believe that is one of the standard parts of the Arduino system and you probably use it all the time without realising it.

Used to be required to be included in a very early version of the IDE. :grinning:

Paul__B: Used to be required to be included in a very early version of the IDE. :grinning:

It is in my version 1.8.6 - I have assumed it is #included in the background by some of the other Arduino code and only needs to be explicitly included where some of its content is needed by code in my own .h files

...R