Reducing File Size

I am using the following code for an Arduino UNO, there is not the option to upgrade to a mega.
When I compile the code it comes to 99% of maximum allowable file size for the Arduino. The file does upload but the readings are spontaneous and irregular.

I am a rookie programmer can anyone suggest a way to help reduce to total maximum size of the sketch please you would be a life saver? Maybe help me with the naming of variables?

#include <SparkFunLSM9DS1.h>
//#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
#include <TouchScreen.h>
#include <SD.h>
#include <SparkFun_APDS9960.h>
#include <SoftwareSerial.h>

SoftwareSerial blue(0,1);
SparkFun_APDS9960 apds = SparkFun_APDS9960();
uint16_t a = 0;
uint16_t r = 0;
uint16_t g = 0;
uint16_t b = 0;
LSM9DS1 imu;
#define LSM9DS1_M  0x1E // Would be 0x1C if SDO_M is LOW
#define LSM9DS1_AG  0x6B // Would be 0x6A if SDO_AG is LOW

//Touchscreen X+ X- Y+ Y- pins
#define YP A3  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 9   // can be a digital pin
#define XP 8   // can be a digital pin
#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940
#define MINPRESSURE 10
#define MAXPRESSURE 1000
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
#define SD_CS 4
#define BUFFPIXEL 10

boolean RecordOn = false;

#define FRAME_X 20
#define FRAME_Y 20
#define FRAME_W 280
#define FRAME_H 200

void drawFrame()
  tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ILI9341_BLACK);

void greenBtn()
  RecordOn = true;

void setup(void)
  apds.init() ;
  apds.enableLightSensor(false) ;
//    imu.settings.device.commInterface = IMU_MODE_I2C;
//  imu.settings.device.mAddress = LSM9DS1_M;
//  imu.settings.device.agAddress = LSM9DS1_AG;
//if (!imu.begin())
//  {
//    blue.println("Failed to communicate with LSM9DS1.");
//      while (1)
//      ;
//  }
  blue.print("Initializing SD card...");
  if (!SD.begin(SD_CS)) {
  tft.fillRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ILI9341_GREEN);
  tft.setCursor(FRAME_W/2 - 50, (FRAME_W/4));

void loop()
bmpDraw("FDG.bmp", 0, 0);
//  imu.readAccel();

  blue.print(int(, 2);
  blue.print(", ");
  blue.print(int(imu.ay), 2);
  blue.print(", ");
  blue.print(int(, 2);
  blue.println(" g");

void detectpressure (){
    // Retrieve a point  
  TSPoint p = ts.getPoint();
  // See if there's any  touch data for us
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
    // Scale using the calibration #'s
    // and rotate coordinate system
    p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
    p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());
    int y = tft.height() - p.x;
    int x = p.y;

   if (RecordOn == false)
      if((x > FRAME_X) && (x < (FRAME_X + FRAME_W))) {
        if ((y > FRAME_Y) && (y <= (FRAME_Y + FRAME_H))) {
          blue.println("Green btn hit"); 

void bmpDraw(char *filename, uint8_t x, uint16_t y) {

  File     bmpFile;
  int      bmpWidth, bmpHeight;   // W+H in pixels
  uint8_t  bmpDepth;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;        // Start of image data in file
  uint32_t rowSize;               // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
  uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  goodBmp = false;       // Set to true on valid header parse
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();

  if((x >= tft.width()) || (y >= tft.height())) return;

  blue.print(F("Loading image '"));

  // Open requested file on SD card
  if ((bmpFile = == NULL) {
    blue.print(F("File not found"));

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    blue.print(F("File size: ")); blue.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    blue.print(F("Image Offset: ")); blue.println(bmpImageoffset, DEC);
    // Read DIB header
    blue.print(F("Header size: ")); blue.println(read32(bmpFile));
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      blue.print(F("Bit Depth: ")); blue.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        blue.print(F("Image size: "));

        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;

        // If bmpHeight is negative, image is in top-down order.
        // This is not canon but has been observed in the wild.
        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width())  w = tft.width()  - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x+w-1, y+h-1);

        for (row=0; row<h; row++) { // For each scanline...

          // Seek to start of scan line.  It might seem labor-
          // intensive to be doing this on every line, but this
          // method covers a lot of gritty details like cropping
          // and scanline padding.  Also, the seek only takes
          // place if the file position actually needs to change
          // (avoids a lot of cluster math in SD library).
          if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else     // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if(bmpFile.position() != pos) { // Need seek?
            buffidx = sizeof(sdbuffer); // Force buffer reload

          for (col=0; col<w; col++) { // For each pixel...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
    , sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning

            // Convert pixel from BMP to TFT format, push to display
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
          } // end pixel
        } // end scanline
        blue.print(F("Loaded in "));
        blue.print(millis() - startTime);
        blue.println(" ms");
      } // end goodBmp

  if(!goodBmp) blue.println(F("BMP format not recognized."));

// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.

uint16_t read16(File &f) {
  uint16_t result;
  ((uint8_t *)&result)[0] =; // LSB
  ((uint8_t *)&result)[1] =; // MSB
  return result;

uint32_t read32(File &f) {
  uint32_t result;
  ((uint8_t *)&result)[0] =; // LSB
  ((uint8_t *)&result)[1] =;
  ((uint8_t *)&result)[2] =;
  ((uint8_t *)&result)[3] =; // MSB
  return result;

can anyone suggest a way to help reduce to total maximum size of the sketch please

What functionality do you want to give up?

there is not the option to upgrade to a mega.

Even if it spells the difference between success and failure? If size is the limiting factor, there are Mega clones in the Uno size.

Ideally I want to keep the functionality but optimise the current code I have with different for statements, change variable names or optimise in other form I do not currently no about

  blue.print(F("Loading image '"));
  blue.print("Initializing SD card...");

Consistently using the F-macro may help. It certainly won't hurt.

Are you out of Flash or RAM?

Post the compiler output.

F() macro helps save ram, but you lose I think 2 bytes of flash every time you use it - I've been in a situation where I had to remove a few F() macros to get it to fit in flash.

You can fill flash to 100% without it negatively impacting operation of the program. You cannot do the same with RAM, because the compiler can only tell you the memory used by global and static variables, not local variables and dynamicall allocated memory.

Also, software serial at 115200? That's asking for trouble... A Mega or a 1284p-based board would be a much better fit for your project - not only do they have more flash and ram, but they have a hardware serial so you could ditch the software serial.

F() macro helps save ram, but you lose I think 2 bytes of flash every time you use it

1964 vs 1964. Exactly the same amount of Flash.

// 1964
#define FT(s) s

// 1964
//#define FT(s) F(s)

void setup() 
  Serial.begin( 250000 );

  Serial.println( "zero" );

  Serial.println( FT( "one" ) );
  Serial.println( FT( "two" ) );
  Serial.println( FT( "three" ) );

  Serial.println( F( "four" ) );

void loop() 

the 115200 baudrate is the recommended rate for the bluetooth device?

my sketch is at 97% capacity for program storage space and 72% for dynamic memory. I am hoping to incorporate more images into my current program but it is not possible at this stage

the 115200 baudrate is the recommended rate for the bluetooth device?

The code in reply #5 is solely to demonstrate the merits of using the F-macro. It reduces SRAM usage but has no affect on Flash usage.

In other words... Consistently using the F-macro may help. It certainly won't hurt.

change variable names

Variable names are mapped to address by the compiler. int i and int thisHereIsALoopIndexThatGoesFromSeroToTwoHundredFiftyFize take up exactly the same amount of flash.

SoftwareSerial blue(0,1);

Why are you using SoftwareSerial on the hardware serial pins? Ditch that, and save a bunch of memory.


Don't you know that loop() loops?

uint32_t read32(File &f) {
  uint32_t result;
  for (byte i=0; i<4; i++)
    ((uint8_t *)&result)[i] =;
  return result;

and ditch the bootloader by programming it from the ICSP instead of serial. This will also free up the hardware serial port so you don't have to use software serial for bluetooth.