Arduino Sketch too Big; How to Shorten it?

Hi all!

I am making a speedometer using the DFRobot Bluno board. I am only using three main things; GPS, 2.8" display, and Blynk. The sketch is too big though. After failing programming, it says this:

Sketch uses 35000 bytes (108%) of program storage space. Maximum is 32256 bytes.
Global variables use 1740 bytes (84%) of dynamic memory, leaving 308 bytes for local variables. Maximum is 2048 bytes.
text section exceeds available space in board
Sketch too big; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing it.
Error compiling for board Arduino Uno.

I took a look at this website:

I then deleted all the extra text and unused code, but its still too big!
What else can I do?

Here's the code:

#define BLYNK_PRINT Serial

#include <DFRobot_GDL.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <BlynkSimpleSerialBLE.h>

#define TFT_DC  8
#define TFT_CS  10
#define TFT_RST 9

char auth[] = "****************************************";

int last = 0;
int lastTime = 0;

boolean noData=true;

float LAT;
float LON;

float topSpeed;
float Speed;
float Course;
float Alt;
float aveSpeed;
float aveSpeeds;
int Sat;
int readingCount;
int maxReadingCount = 15;

static const int RXPin = 3, TXPin = 2;
static const uint32_t GPSBaud = 9600;

DFRobot_ILI9488_320x480_HW_SPI screen(TFT_DC,TFT_CS,TFT_RST);
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);

static const double HOME_LAT = **.******, HOME_LON = -**.******;
double distanceToHome = 
        TinyGPSPlus::distanceBetween(
          gps.location.lat(),
          gps.location.lng(),
          HOME_LAT, 
          HOME_LON);
      double courseToHome =
        TinyGPSPlus::courseTo(
          gps.location.lat(),
          gps.location.lng(),
          HOME_LAT, 
          HOME_LON);
          
#define screenColor COLOR_RGB565_NAVY
#define backColor COLOR_RGB565_DGRAY

void setup() {  
  Blynk.begin(Serial, auth);
  ss.begin(GPSBaud);
  
  screen.begin();
  screen.setRotation(1);
  screen.fillScreen(COLOR_RGB565_WHITE);
  screen.fillRoundRect(0, 0, 480, 320, 15, backColor);
  screen.fillRoundRect(7, 7, 466, 306, 15, screenColor);

  //title
  screen.setTextColor(COLOR_RGB565_CYAN);
  screen.setTextSize(3);
  screen.setCursor(70, 13);
  screen.print("GPS Speedometer");

  screen.setTextSize(1);

  //title underline
  screen.drawLine(20, 50, 460, 50, 0x0700);

  //speed
  screen.drawRoundRect(30, 60, 205, 65, 15, 0x0700);
  screen.setCursor(200,64);
  screen.print("MPH");

  //course
  screen.drawRoundRect(245, 60, 205, 65, 15, 0x0700);
  screen.setCursor(415,64);
  screen.print("DEG"); 
  
  //altitude
  screen.drawRoundRect(30, 135, 205, 65, 15, 0x0700);
  screen.setCursor(200,140);
  screen.print("FT");
  
  //direction
  screen.drawRoundRect(245, 135, 205, 65, 15, 0x0700);
  screen.setCursor(415,140);
  screen.print("ROS");
  
  //latitude
  screen.drawRoundRect(30, 210, 205, 45, 15, 0x0700);
  screen.setCursor(200,64);
  screen.print("MPH");
  
  //longitude
  screen.drawRoundRect(245, 210, 205, 45, 15, 0x0700);
  screen.setCursor(200,64);
  screen.print("MPH");
  
  //time
  screen.drawRoundRect(30, 265, 205, 45, 15, 0x0700);
  screen.setCursor(200,64);
  screen.print("MPH");
  
  //date
  screen.drawRoundRect(245, 265, 205, 45, 15, 0x0700);
  screen.setCursor(200,64);
  screen.print("MPH");
  
  last = millis();
  lastTime = millis();
}

void loop(){
  screen.setTextColor(COLOR_RGB565_GREEN);
  screen.setTextSize(3);
    
  while (ss.available() > 0){
    if (gps.location.isUpdated()){
      gps.encode(ss.read());
      //lastTime = millis();
    }
    readingCount++;
    LAT = gps.location.lat();
    LON = gps.location.lng();
    if (millis() - last > 1000){
      displayData();
      last = millis();
    }
    Blynk.virtualWrite(V0, 4, LAT, LON, "Sailboat");
  }
  
  if (gps.speed.isUpdated()){
    Speed = gps.speed.mph();
    aveSpeeds += Speed;
    Blynk.virtualWrite(V1, Speed);
  }

  else if (gps.course.isUpdated()){
    Course = gps.course.deg();
    Blynk.virtualWrite(V2, Course);
  }

  else if (gps.altitude.isUpdated()){
    Alt = gps.altitude.feet();
    Blynk.virtualWrite(V3, Alt);
  }
  
  else if (gps.satellites.isUpdated()){
    Sat = gps.satellites.value();
    Blynk.virtualWrite(V4, Sat);
  }

  Blynk.run();
}


void displayData(){
  //speed
  screen.fillRect(110,78,120,25,screenColor);
  screen.setCursor(45, 80);
  screen.print("SPD: ");
  screen.println(Speed);

  //course
  screen.fillRect(325,78,120,25,screenColor);
  screen.setCursor(260, 80);
  if (Course >= 100){
    screen.print("CSE:");
  }
  else {
    screen.print("CSE: ");
  }
  screen.println(Course);

  //altitude
  screen.setCursor(45, 155);
  if (Alt >= 100 && Alt < 1000){
    screen.fillRect(110,153,120,25,screenColor);
    screen.print("ALT:");
  }
  else if (Alt >= 1000){
    screen.fillRect(70,153,160,25,screenColor);
    screen.print("A: ");
  }
  else {
    screen.fillRect(110,153,120,25,screenColor);
    screen.print("ALT: ");
  }
  screen.println(Alt);

  //direction
  screen.fillRect(330,153,80,25,screenColor);
  screen.setCursor(260, 155);
  screen.print("DIR: ");
  if (Course >= 345 && Course <= 365){
    screen.println("N");
  }
  else if (Course >= 0 && Course <= 20){
    screen.println("N");
  }
  else if (Course >= 21 && Course <= 69){
    screen.println("NE");
  }
  else if (Course >= 70 && Course <= 110){
    screen.println("E");
  }
  else if (Course >= 111 && Course <= 169){
      screen.println("SE");
  }
  else if (Course >= 160 && Course <= 200){
    screen.println("S");
  }
  else if (Course >= 201 && Course <= 249){
    screen.println("SW");
  }
  else if (Course >= 250 && Course <= 290){
    screen.println("W");
  }
  else if (Course >= 291 && Course <= 344){
    screen.println("NW");
  }

  //top speed
  if (Speed > topSpeed){
    topSpeed = Speed;
  }
  screen.fillRect(92,223,135,25,screenColor);
  screen.setCursor(45, 225);
  screen.print("TS: ");
  screen.print(topSpeed);

  //average speed
  if (readingCount == maxReadingCount){
    aveSpeed = aveSpeeds / maxReadingCount;
    screen.fillRect(307,223,135,25,screenColor);
    screen.setCursor(260, 225);
    screen.print("AS: ");
    screen.print(aveSpeed);
    readingCount = 0;
    aveSpeeds = 0;
  }

  //lat and lng
  screen.setTextSize(2);
    
  screen.fillRect(90,278,140,18,screenColor);//screenColor
  screen.setCursor(45, 280);
  screen.print("LAT:");
  screen.println(LAT, 6);
    
  screen.fillRect(305,278,140,18,screenColor);
  screen.setCursor(260, 280);
  screen.print("LON:");
  screen.println(LON, 6);

  screen.setTextSize(3);

  //satellites
  screen.setTextColor(COLOR_RGB565_WHITE);
  screen.setTextSize(2);
  screen.fillRect(435,10,28,18,screenColor);
  screen.setCursor(390, 12);
  screen.print("SAT:");
  screen.println(Sat);
}

Thanks in advance!

Doubles on a Uno are just floats. Floats take a lot of space why not use longs instead? If you really need doubles get a 32bit MCU

TnyyGPS++ is a big library

This has redundant tests, once you've excluded 0-20 you don't need to check for <21 again. It can be nested like

  else if (Course >= 0 && Course <= 20){
    screen.println("N");
  }
  else if (Course <= 69){
    screen.println("NE");
  }
  else if (Course <= 110){
    screen.println("E");
  }

and so forth

Hi @Idahowalker
Can longs store decimal points?

Do you mean fractional quantities?

See post 5

Yes.

I just tried what you suggested. Now the size is at 34860 bytes.

You have many sequences of similar print statements like that. As they all have the same form (and some values are common like 0x0700 for example), you should make them into functions and pass different parameters to them.

Have you ever looked at using millis()? The concept is that a millis() is one milli second of time; which is a fraction. millis() are not used types as floats, millis are typed as long integers. Where an integer number is used to represent a fraction.

millis() shows a fraction of a time using a unsigned long. Say 1407 millis is 1.407 seconds. See how the long is being used to store a fraction? If millis() returns a 50 as an unsigned long to get the fraction just divide by 1000, which you only need to do for when you want to display the info to humans.

If you make updates please re-post the revised sketch.

Ah, that make sense. So when I assign a long variable data, I just multiply the data * 1000 before doing so. Then when I display the data, I just divide it by 1000 first.

Sorry, here it is (size = 34746 bytes):

#define BLYNK_PRINT Serial

#include <DFRobot_GDL.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <BlynkSimpleSerialBLE.h>

#define TFT_DC  8
#define TFT_CS  10
#define TFT_RST 9

char auth[] = "**********************";

int last = 0;
int lastTime = 0;

boolean noData=true;

float LAT;
float LON;

float topSpeed;
float Speed;
float Course;
float Alt;
float aveSpeed;
float aveSpeeds;
int Sat;
int readingCount;
int maxReadingCount = 15;

static const int RXPin = 3, TXPin = 2;
static const uint32_t GPSBaud = 9600;

DFRobot_ILI9488_320x480_HW_SPI screen(TFT_DC,TFT_CS,TFT_RST);
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);

static const double HOME_LAT = **.******, HOME_LON = -**.******;
double distanceToHome =
        TinyGPSPlus::distanceBetween(
          gps.location.lat(),
          gps.location.lng(),
          HOME_LAT, 
          HOME_LON);
      double courseToHome =
        TinyGPSPlus::courseTo(
          gps.location.lat(),
          gps.location.lng(),
          HOME_LAT, 
          HOME_LON);
          
#define screenColor COLOR_RGB565_NAVY
#define backColor COLOR_RGB565_DGRAY

void setup() {  
  Blynk.begin(Serial, auth);
  ss.begin(GPSBaud);
  
  screen.begin();
  screen.setRotation(1);
  screen.fillScreen(COLOR_RGB565_WHITE);
  screen.fillRoundRect(0, 0, 480, 320, 15, backColor);
  screen.fillRoundRect(7, 7, 466, 306, 15, screenColor);

  //title
  screen.setTextColor(COLOR_RGB565_CYAN);
  screen.setTextSize(3);
  screen.setCursor(70, 13);
  screen.print("GPS Speedometer");

  screen.setTextSize(1);

  //title underline
  screen.drawLine(20, 50, 460, 50, 0x0700);

  //speed
  screen.drawRoundRect(30, 60, 205, 65, 15, 0x0700);
  screen.setCursor(200,64);
  screen.print("MPH");

  //course
  screen.drawRoundRect(245, 60, 205, 65, 15, 0x0700);
  screen.setCursor(415,64);
  screen.print("DEG"); 
  
  //altitude
  screen.drawRoundRect(30, 135, 205, 65, 15, 0x0700);
  screen.setCursor(200,140);
  screen.print("FT");
  
  //direction
  screen.drawRoundRect(245, 135, 205, 65, 15, 0x0700);
  screen.setCursor(415,140);
  screen.print("ROS");
  
  //latitude
  screen.drawRoundRect(30, 210, 205, 45, 15, 0x0700);
  
  //longitude
  screen.drawRoundRect(245, 210, 205, 45, 15, 0x0700);
  
  //time
  screen.drawRoundRect(30, 265, 205, 45, 15, 0x0700);
  
  //date
  screen.drawRoundRect(245, 265, 205, 45, 15, 0x0700);
  
  last = millis();
  lastTime = millis();
}

void loop(){
  screen.setTextColor(COLOR_RGB565_GREEN);
  screen.setTextSize(3);
    
  while (ss.available() > 0){
    if (gps.location.isUpdated()){
      gps.encode(ss.read());
      //lastTime = millis();
    }
    readingCount++;
    LAT = gps.location.lat();
    LON = gps.location.lng();
    if (millis() - last > 1000){
      displayData();
      last = millis();
    }
    Blynk.virtualWrite(V0, 4, LAT, LON, "Sailboat");
  }
  
  if (gps.speed.isUpdated()){
    Speed = gps.speed.mph();
    aveSpeeds += Speed;
    Blynk.virtualWrite(V1, Speed);
  }

  else if (gps.course.isUpdated()){
    Course = gps.course.deg();
    Blynk.virtualWrite(V2, Course);
  }

  else if (gps.altitude.isUpdated()){
    Alt = gps.altitude.feet();
    Blynk.virtualWrite(V3, Alt);
  }
  
  else if (gps.satellites.isUpdated()){
    Sat = gps.satellites.value();
    Blynk.virtualWrite(V4, Sat);
  }

  Blynk.run();
}


void displayData(){
  //speed
  screen.fillRect(110,78,120,25,screenColor);
  screen.setCursor(45, 80);
  screen.print("SPD: ");
  screen.println(Speed);

  //course
  screen.fillRect(325,78,120,25,screenColor);
  screen.setCursor(260, 80);
  if (Course >= 100){
    screen.print("CSE:");
  }
  else {
    screen.print("CSE: ");
  }
  screen.println(Course);

  //altitude
  screen.setCursor(45, 155);
  if (Alt >= 100 && Alt < 1000){
    screen.fillRect(110,153,120,25,screenColor);
    screen.print("ALT:");
  }
  else if (Alt >= 1000){
    screen.fillRect(70,153,160,25,screenColor);
    screen.print("A: ");
  }
  else {
    screen.fillRect(110,153,120,25,screenColor);
    screen.print("ALT: ");
  }
  screen.println(Alt);

  //direction
  screen.fillRect(330,153,80,25,screenColor);
  screen.setCursor(260, 155);
  screen.print("DIR: ");
  if (Course >= 345 && Course <= 365){
    screen.println("N");
  }
  else if (Course >= 0 && Course <= 20){
    screen.println("N");
  }
  else if (Course <= 69){
    screen.println("NE");
  }
  else if (Course <= 110){
    screen.println("E");
  }
  else if (Course <= 169){
      screen.println("SE");
  }
  else if (Course <= 200){
    screen.println("S");
  }
  else if (Course <= 249){
    screen.println("SW");
  }
  else if (Course <= 290){
    screen.println("W");
  }
  else if (Course <= 344){
    screen.println("NW");
  }

  //top speed
  if (Speed > topSpeed){
    topSpeed = Speed;
  }
  screen.fillRect(92,223,135,25,screenColor);
  screen.setCursor(45, 225);
  screen.print("TS: ");
  screen.print(topSpeed);

  //average speed
  if (readingCount == maxReadingCount){
    aveSpeed = aveSpeeds / maxReadingCount;
    screen.fillRect(307,223,135,25,screenColor);
    screen.setCursor(260, 225);
    screen.print("AS: ");
    screen.print(aveSpeed);
    readingCount = 0;
    aveSpeeds = 0;
  }

  //lat and lng
  screen.setTextSize(2);
    
  screen.fillRect(90,278,140,18,screenColor);//screenColor
  screen.setCursor(45, 280);
  screen.print("LAT:");
  screen.println(LAT, 6);
    
  screen.fillRect(305,278,140,18,screenColor);
  screen.setCursor(260, 280);
  screen.print("LON:");
  screen.println(LON, 6);

  screen.setTextSize(3);

  //satellites
  screen.setTextColor(COLOR_RGB565_WHITE);
  screen.setTextSize(2);
  screen.fillRect(435,10,28,18,screenColor);
  screen.setCursor(390, 12);
  screen.print("SAT:");
  screen.println(Sat);
}

Doing good so far.

So there are unsigned ints, and unsigned longs. An unsigned int on a Uno, unsigned int - Arduino Reference can store a pretty good sized fractional value without taking up the space as a double.

Ummm, I just tried that for only two variables; Speed, and Top speed. Now the sketch size is 35098 bytes. Maybe I did something wrong?

Here is a link the language reference, Arduino Reference - Arduino Reference. Look through the various data types and pick the ones that best suit your program requirements or get a bigger MCU.

Making suggestions is all I am able to do for you. I do not own Uno's, I only use ESP32's. I cannot replicate your issue, the ESP32 does not have the memory limitations of an Uno.

1 Like

Longs use the same amount of space as floats and doubles.
"Long variables are extended size variables for number storage, and store 32 bits (4 bytes), from -2,147,483,648 to 2,147,483,647"

I've got it down to 33604 bytes now:

#include <DFRobot_GDL.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <BlynkSimpleSerialBLE.h>

#define TFT_DC  8
#define TFT_CS  10
#define TFT_RST 9

int last = 0;

boolean noData=true;

float LAT;
float LON;

float topSpeed;
float Speed;
float Course;
float Alt;
float aveSpeed;
float aveSpeeds;
int Sat;
int readingCount;
int maxReadingCount = 15;

DFRobot_ILI9488_320x480_HW_SPI screen(TFT_DC,TFT_CS,TFT_RST);
TinyGPSPlus gps;
SoftwareSerial ss(3, 4);

static const double HOME_LAT = **.******, HOME_LON = -**.******;
double distanceToHome =
        TinyGPSPlus::distanceBetween(
          gps.location.lat(),
          gps.location.lng(),
          HOME_LAT, 
          HOME_LON);
      double courseToHome =
        TinyGPSPlus::courseTo(
          gps.location.lat(),
          gps.location.lng(),
          HOME_LAT, 
          HOME_LON);

#define screenColor COLOR_RGB565_NAVY
#define backColor COLOR_RGB565_DGRAY

void setup() {  
  Blynk.begin(Serial, "****************************");
  ss.begin(9600);
  
  screen.begin();
  screen.setRotation(1);
  screen.fillScreen(COLOR_RGB565_WHITE);
  screen.fillRoundRect(0, 0, 480, 320, 15, backColor);
  screen.fillRoundRect(7, 7, 466, 306, 15, screenColor);

  //title
  screen.setTextColor(COLOR_RGB565_CYAN);
  screen.setTextSize(3);
  screen.setCursor(70, 13);
  screen.print("GPS Speedometer");

  screen.setTextSize(1);

  //title underline
  screen.drawLine(20, 50, 460, 50, 0x0700);

  //speed
  screen.drawRoundRect(30, 60, 205, 65, 15, 0x0700);
  //screen.setCursor(200,64);
  //screen.print("MPH");

  //course
  screen.drawRoundRect(245, 60, 205, 65, 15, 0x0700);
  //screen.setCursor(415,64);
  //screen.print("DEG"); 
  
  //altitude
  screen.drawRoundRect(30, 135, 205, 65, 15, 0x0700);
  //screen.setCursor(200,140);
  //screen.print("FT");
  
  //direction
  screen.drawRoundRect(245, 135, 205, 65, 15, 0x0700);
  //screen.setCursor(415,140);
  //screen.print("ROS");
  
  //latitude
  screen.drawRoundRect(30, 210, 205, 45, 15, 0x0700);
  
  //longitude
  screen.drawRoundRect(245, 210, 205, 45, 15, 0x0700);
  
  last = millis();

  screen.setTextColor(COLOR_RGB565_GREEN);
  screen.setTextSize(3);
}

void loop(){
    
  while (ss.available() > 0){
    if (gps.location.isUpdated()){
      gps.encode(ss.read());
    }
    readingCount++;
    LAT = gps.location.lat();
    LON = gps.location.lng();
    if (millis() - last > 1000){
      displayData();
      last = millis();
    }
    Blynk.virtualWrite(V0, 4, LAT, LON, "Sailboat");
  }
  
  if (gps.speed.isUpdated()){
    Speed = gps.speed.mph();
    aveSpeeds += Speed;
    Blynk.virtualWrite(V1, Speed);
  }

  else if (gps.course.isUpdated()){
    Course = gps.course.deg();
    Blynk.virtualWrite(V2, Course);
  }

  else if (gps.altitude.isUpdated()){
    Alt = gps.altitude.feet();
    Blynk.virtualWrite(V3, Alt);
  }
  
  else if (gps.satellites.isUpdated()){
    Sat = gps.satellites.value();
    Blynk.virtualWrite(V4, Sat);
  }

  Blynk.run();
}


void displayData(){
  //speed
  screen.fillRect(110,78,120,25,screenColor);
  screen.setCursor(45, 80);
  screen.print("SPD: ");
  screen.println(Speed);

  //course
  screen.fillRect(325,78,120,25,screenColor);
  screen.setCursor(260, 80);
  if (Course >= 100){
    screen.print("CSE:");
  }
  else {
    screen.print("CSE: ");
  }
  screen.println(Course);

  //altitude
  screen.setCursor(45, 155);
  if (Alt >= 100 && Alt < 1000){
    screen.fillRect(110,153,120,25,screenColor);
    screen.print("ALT:");
  }
  else if (Alt >= 1000){
    screen.fillRect(70,153,160,25,screenColor);
    screen.print("A: ");
  }
  else {
    screen.fillRect(110,153,120,25,screenColor);
    screen.print("ALT: ");
  }
  screen.println(Alt);

  //direction
  screen.fillRect(330,153,80,25,screenColor);
  screen.setCursor(260, 155);
  screen.print("DIR: ");
  
  if (Course >= 0 && Course <= 20){
    screen.println("N");
  }
  else if (Course <= 69){
    screen.println("NE");
  }
  else if (Course <= 110){
    screen.println("E");
  }
  else if (Course <= 169){
      screen.println("SE");
  }
  else if (Course <= 200){
    screen.println("S");
  }
  else if (Course <= 249){
    screen.println("SW");
  }
  else if (Course <= 290){
    screen.println("W");
  }
  else if (Course <= 344){
    screen.println("NW");
  }
  else if (Course <= 365){
    screen.println("N");
  }
  
  //top speed
  if (Speed > topSpeed){
    topSpeed = Speed;
    screen.fillRect(92,223,135,25,screenColor);
    screen.setCursor(45, 225);
    screen.print("TS: ");
    screen.print(topSpeed);
  }

  //average speed
  if (readingCount == maxReadingCount){
    aveSpeed = aveSpeeds / maxReadingCount;
    screen.fillRect(307,223,135,25,screenColor);
    screen.setCursor(260, 225);
    screen.print("AS: ");
    screen.print(aveSpeed);
    readingCount = 0;
    aveSpeeds = 0;
  }

  //lat and lng
  screen.setTextSize(2);
    
  screen.fillRect(90,278,140,18,screenColor);//screenColor
  screen.setCursor(45, 280);
  screen.print("LAT:");
  screen.println(LAT, 6);
    
  screen.fillRect(305,278,140,18,screenColor);
  screen.setCursor(260, 280);
  screen.print("LON:");
  screen.println(LON, 6);

  screen.setTextSize(3);

  //satellites
  screen.setTextColor(COLOR_RGB565_WHITE);
  screen.setTextSize(2);
  screen.fillRect(435,10,28,18,screenColor);
  screen.setCursor(390, 12);
  screen.print("SAT:");
  screen.println(Sat);
}

Use the F macro for print statements.

  screen.print( F("SAT:") );

it will place the strings in flash memory (or is that what we're running low on? I forget...)

byte - Arduino Reference

That the int stores only a 15 a int is not required, instead use a byte for number of less than byte size.

1 Like

and make it const so the compiler can optimize it to nothing

const byte maxReadingCount = 15;

Constant should be declared const for safety too, so they can't be accidentally modified.