Reducing the dynamic memory of my sketch


Currently my sketch is on 111% of dynamic memory and so won’t upload. Any suggestions on how to reduce this. I am using this with an arduino nano and the project is a speedcoach

Thanks Tom

#include <SPI.h>
#include <SandTimer.h>
#include <millisDelay.h>
#include <Adafruit_GPS.h>   //Libraries
#define GPSSerial Serial
Adafruit_GPS GPS(&GPSSerial);
SandTimer timer1;
#define GPSECHO false
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>   
U8G2_SSD1309_128X64_NONAME0_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
uint32_t timer = millis();
const int chipSelect = 4;
float ms = 0; //Meters/Second variable
float avems = 0;  //Average M/S variable
float mscounter = 0;  //Speed total (for average)
int integcounter = 0; //Counts half-seconds
float meterstraveled = 0; //Total meters
int splittotal = 0;   //Split total (in seconds)  (Essential to be an integer)
int splitseconds = 0; //Seconds on split display  (Essential to be an integer)
int splitminutes = 0; //Minutes on split display  (Essential to be an integer)
int seconds = 0;
int minutes = 0;
int hours = 0;    //Self-explanatory (for timers)
int splitaveragetotal = 0; //All split seconds added together (for average split)
int splitaverageseconds = 0; //Split average seconds
int splitaverageminutes = 0; //Split average minutes
int splitaverage = 0; //Split average
int splitaveragesecondsdisp = 0; //Display variables, fixes a bug
int splitaverageminutesdisp = 0; 
float splitmdisp = 0; 
float splitsdisp = 0;  //Display Variables
int tc = 0; //Counter variable
int dp = 0; //Data-point variable
int dpave = 0; //Average of the data-points
int dprec = 0; //Counter variable
float knot = 0;//Speed in knots recorded from GPS
float aveknots = 0;  //Speed in knots averaged over 1/2 second (equal to 1 data point and 5 knot readings)
int knotcounter = 0; //Counter variable
int sensorValue = analogRead(A3); //For the data write switch
float msfm = 0; //M/S for the meters calculation

millisDelay secdelay;   //Timing delay (for timer)

void setup() {
  float voltage = sensorValue * (5.0 / 1023.0);   //Converts A3 reading into a 5v equivalent
delay(1000);    //GPS initialization
int realhours = GPS.hour - 8;
if(realhours < 0) {realhours = realhours+24;} //For SD timestamp (24 hour format)

const char s[] PROGMEM = "Progmem";
const char s1[] PROGMEM  = "ABC" ;
const char s2[] PROGMEM  = "DEF" ;
const char s3[] PROGMEM  = "GHI" ;
const char s4[] PROGMEM  = "SMT" ;

const char *a[] = { s1, s2, s3, s4 };
void loop() {

  sensorValue = analogRead(A3);
  float voltage = sensorValue * (5.0 / 1023.0);

  if (secdelay.justFinished()) {seconds++; secdelay.repeat();} //Checks if 1 second has passed, updates seconds variable
  if (seconds == 60) {seconds = 0; minutes++;}                 //Checks if 60 seconds have passed, resets seconds, increases minutes
  if (minutes == 60) {minutes = 0; hours++;}                   //Checks if 60 minutes have passed, resets minutes, increases hours
  char c =;
  if (GPSECHO)
    if (c) Serial.print(c);
  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA()));  //Serial GPS info for debugging
  if (timer > millis()) timer = millis();   //Restarts main timer
    if (timer1.finished()) {knot = knot+GPS.speed; knotcounter++;
  if (millis() - timer > 500) {   //Runs every half-second (responsible for screen-flicker)
    timer = millis(); // Resets timer
     if (GPS.fix) {
      aveknots = knot/knotcounter;
      ms = (aveknots*0.5144444); //Converts knots to meters/second
      knot = 0;
      tc = 0;
      knotcounter = 0;
      aveknots = 0;
      if (ms <= 0.75) {u8g2.clearBuffer();         // clear the internal memory
                       u8g2.setFont(u8g2_font_courR08_tr); // choose a suitable font
                       u8g2.drawStr(0,10,"Error: IDLE");  // write something to the internal memory
                       u8g2.drawStr(1,10,"Battery: ");
                       u8g2.sendBuffer();          // transfer internal memory to the display  
      if (ms > 0.75) 
      msfm = ms;
      mscounter = (mscounter+msfm);  //Continually adds speed to total (for averages)
      integcounter = (integcounter+1); //Adds +1 to variable every half second (for averages)
      avems = mscounter/integcounter; //Generates average meters/second (for total)
      meterstraveled = avems*(integcounter/2); //Calculates total (meters/second divided by seconds)
      meterstraveled = round(meterstraveled);
      splittotal = 500/(ms); //Generates seconds per 500m
      dp = dp + splittotal;  //Adds data-points for dpave variable
      if (dprec >= 6) {dpave = dp/6; //Calculates average
                       dprec = 0; 
                       dp = 0; //Resets data-points and counter variable

      splitminutes = dpave/60; //Generates split minutes from split seconds 
      splitseconds = dpave - (splitminutes*60); //Displays remaining seconds
      splitaveragetotal = splitaveragetotal+splittotal;   //All split times (in seconds) added together
      splitaverage = splitaveragetotal/(integcounter);  //Averages out split times w/ seconds
      splitaverageminutes = splitaverage/60;   //Calculates split minutes
      splitaverageseconds = splitaverage-splitaverageminutes*60;   //Calculates split seconds
      splitaverageminutesdisp = splitaverageminutes;
      splitaveragesecondsdisp = splitaverageseconds;
      splitmdisp = splitminutes;
      splitsdisp = splitseconds;      //Display variables
      u8g2.clearBuffer();          // clear the internal memory
      u8g2.setFont(u8g2_font_courR08_tr); // choose a suitable font --------------------CHANGE THIS FONT TO SOMETHING LARGER
      u8g2.setCursor(0, 25);
      u8g2.setCursor(1, 25);
      u8g2.setCursor(1, 75);
      u8g2.print(splitsdisp); //adjust pixels to get a good display
      u8g2.sendBuffer();          // transfer internal memory to the display  


Can you use a text-only display library?

Yes possibly, any suggestions as to which one for my SSD109 display?

Doesn’t the U8g2 have a text-only version? U8x8lib, or something like that?

I've tried to use that and to use the examples of the library but they all come up with this error: U8X8_SSD1309_128X64_NONAME0_F_4W_SW_SPI' does not name a type

Any suggestions on how to fix this?

I've tried to use that and to use the examples of the library but they all come up with this error: U8X8_SSD1309_128X64_NONAME0_F_4W_SW_SPI' does not name a type

Any suggestions on how to fix this?

Use the correct constructor name: u8x8setupcpp · olikraus/u8g2 Wiki · GitHub

In you case this would be: U8X8_SSD1309_128X64_NONAME0_4W_SW_SPI

Another option would be to use the first page/next page approach instead of the full buffer constructor: This means instead of U8G2_SSD1309_128X64_NONAME0_F_4W_SW_SPI use U8G2_SSD1309_128X64_NONAME0_1_4W_SW_SPI. However in this case I strongly suggest to study the page buffer examples, because this approach is different from the full buffer method.

If everything works, also try to use HW SPI. It will be much faster.