Whats up with Mega 2560 IDE Sketch Size

Hi, I've been working on a sketch for some time and it appears I've hit the limit however the IDE is saying I haven't.

Binary sketch size: 246,010 bytes (of a 258,048 byte maximum)

When I try to upload this size the mega 2560 takes the upload but it doesn't turn back on. It locks up and doesn't even read the first line in the setup(). If I remove about 600 bytes of code (simple stuff like myGLCD.drawline) it will turn back on.

Is there anything I can do to free up that remaining space the IDE says I have? Or anyway to optimize what I have without re-writing. I'm getting close to finishing but will need all 258kbs.

Is there anything I can do to free up that remaining space the IDE says I have?

It's probably not code space that is the issue. You are probably running out of SRAM.

But I ruled that out by only having to remove pointless so to speak code. The code I remove has nothing to do with SRAM I don't think? For example I remove the following and it works. Even if I go around the sketch and remove the serial.print tags it works.

  myGLCD.setColor(255, 255, 255); 
  myGLCD.drawLine(0, 450, 799, 450); // on footer 
  myFiles.loadBitmap(376, 426, 48, 48, "schIconL.raw");  // footer home button
  myFiles.loadBitmap(0, 0, 307, 59, "schPwI.raw"); 
  myGLCD.drawLine(71, 54, 799, 54); // under header 

  // grid for schedule
  myGLCD.drawLine(0, 259, 799, 259); // 
  myGLCD.drawLine(0, 414, 799, 414); // 
  myGLCD.drawLine(400, 259, 400, 414); //   

  myFiles.loadBitmap(116, 271, 54, 54, "upM.raw");  // up 
  myFiles.loadBitmap(116, 352, 54, 54, "downM.raw");  // down
  myFiles.loadBitmap(321, 271, 54, 54, "upM.raw");  // up 
  myFiles.loadBitmap(321, 352, 54, 54, "downM.raw");  // down
  myFiles.loadBitmap(516, 271, 54, 54, "upM.raw");  // up 
  myFiles.loadBitmap(516, 352, 54, 54, "downM.raw");  // down
  myFiles.loadBitmap(721, 271, 54, 54, "upM.raw");  // up 
  myFiles.loadBitmap(721, 352, 54, 54, "downM.raw");  // down

  myGLCD.setColor(255, 255, 255);
  myGLCD.setFont(BigFont);
  myGLCD.print("Start Time", 125, 232);
  myGLCD.print("Stop Time", 533, 232); 

  myGLCD.print("Hour", 26, 293);
  myGLCD.print("Minute", 212, 293); 
  myGLCD.print("Hour", 426, 293);
  myGLCD.print("Minute", 612, 293);

I run the following code and it says my SRAM is 1788

int freeRam ()
{
  // Returns available SRAM
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Can someone please explain how byte size works. I find the following to be very strange!

I'm not the greatest programmer, I'm sure this sketch could be half the size however it works great so don't judge. :slight_smile: This is my first attempt at this stuff. Now I'm trying to clean up my mess and remove any duplicate code. Here's a good example of what I'm attempting but my results are not as expected.

Before changing the following code the IDE says 245,104.

void sliderBarStaticMoon ()
{ 
  if ((currentLightMode==0) && (sliderModeHSMoon==0))
  {
    currentColor.Moon = maxRGBW - currentColor.Moon;
    currentColor.Moon = (currentColor.Moon/16.05882352941176);
    myGLCD.fillRect(741,133+currentColor.Moon,774,143+currentColor.Moon);
  }
  else if ((currentLightMode==1) && (sliderModeMSMoon==0))
  {
    currentColor.Moon = maxRGBW - currentColor.Moon;
    currentColor.Moon = (currentColor.Moon/16.05882352941176);
    myGLCD.fillRect(741,133+currentColor.Moon,774,143+currentColor.Moon);
  }
  else if ((currentLightMode==2) && (sliderModeLSMoon==0))
  {
    currentColor.Moon = maxRGBW - currentColor.Moon;
    currentColor.Moon = (currentColor.Moon/16.05882352941176);
    myGLCD.fillRect(741,133+currentColor.Moon,774,143+currentColor.Moon);
  }
  else if ((currentLightMode==3) && (sliderModeMMoon==0))
  {
    currentColor.Moon = maxRGBW - currentColor.Moon;
    currentColor.Moon = (currentColor.Moon/16.05882352941176);
    myGLCD.fillRect(741,133+currentColor.Moon,774,143+currentColor.Moon);
  }
  else
  {
    currentColor.Moon = 255 - currentColor.Moon;
    myGLCD.fillRect(741,133+currentColor.Moon,774,143+currentColor.Moon);
  }
}

After I change the code above to below which is clearly less text my sketch size actually increases. :relaxed: Now it reads 245,142 in the IDE? So obviously there's something I'm missing.

void sliderS8 ()
{
  currentColor.Moon = maxRGBW - currentColor.Moon;
  currentColor.Moon = (currentColor.Moon/16.05882352941176);
  myGLCD.fillRect(741,133+currentColor.Moon,774,143+currentColor.Moon);  
}
void sliderBarStaticMoon ()
{ 
  if ((currentLightMode==0) && (sliderModeHSMoon==0))
  {
    sliderS8();
  }
  else if ((currentLightMode==1) && (sliderModeMSMoon==0))
  {
    sliderS8();
  }
  else if ((currentLightMode==2) && (sliderModeLSMoon==0))
  {
    sliderS8();
  }
  else if ((currentLightMode==3) && (sliderModeMMoon==0))
  {
    sliderS8();
  }
  else
  {
    currentColor.Moon = 255 - currentColor.Moon;
    myGLCD.fillRect(741,133+currentColor.Moon,774,143+currentColor.Moon);
  }
}

I thought doing that would save me a couple hundred bytes.

Are you using Strings or dynamic memory allocation?

I would like to see your whole sketch beause it must be either really big or really inefficient in some parts!

Also do you use latest Arduino software 1.5.8 ? If not, give it a try.

robsworld78:
Can someone please explain how byte size works. I find the following to be very strange!

I thought doing that would save me a couple hundred bytes.

Hi Rob,

You are on the right lines, but chose the wrong type of code to place in a function.

Let me now give you an example of what I did with your earlier code you said you needed to remove.

Original (modified so would compile standalone) :-

#include <UTFT.h>
#include <SdFat.h>
#include <UTFT_tinyFAT.h>
extern uint8_t BigFont[];

UTFT myGLCD(CPLD, 38, 39, 40, 41);
UTFT_tinyFAT myFiles(&myGLCD);

void setup() {
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawLine(0, 450, 799, 450); // on footer
  myFiles.loadBitmap(376, 426, 48, 48, "schIconL.raw");  // footer home button
  myFiles.loadBitmap(0, 0, 307, 59, "schPwI.raw");
  myGLCD.drawLine(71, 54, 799, 54); // under header
  // grid for schedule
  myGLCD.drawLine(0, 259, 799, 259); //
  myGLCD.drawLine(0, 414, 799, 414); //
  myGLCD.drawLine(400, 259, 400, 414); //

  myFiles.loadBitmap(116, 271, 54, 54, "upM.raw");  // up
  myFiles.loadBitmap(116, 352, 54, 54, "downM.raw");  // down
  myFiles.loadBitmap(321, 271, 54, 54, "upM.raw");  // up
  myFiles.loadBitmap(321, 352, 54, 54, "downM.raw");  // down
  myFiles.loadBitmap(516, 271, 54, 54, "upM.raw");  // up
  myFiles.loadBitmap(516, 352, 54, 54, "downM.raw");  // down
  myFiles.loadBitmap(721, 271, 54, 54, "upM.raw");  // up
  myFiles.loadBitmap(721, 352, 54, 54, "downM.raw");  // down

  myGLCD.setColor(255, 255, 255);
  myGLCD.setFont(BigFont);
  myGLCD.print("Start Time", 125, 232);
  myGLCD.print("Stop Time", 533, 232);

  myGLCD.print("Hour", 26, 293);
  myGLCD.print("Minute", 212, 293);
  myGLCD.print("Hour", 426, 293);
  myGLCD.print("Minute", 612, 293);
}
void loop() {
 }

After I had a stab at optimising :-

#include <UTFT.h>
#include <SdFat.h>
#include <UTFT_tinyFAT.h>
extern uint8_t BigFont[];

UTFT myGLCD(CPLD, 38, 39, 40, 41);
UTFT_tinyFAT myFiles(&myGLCD);

void upM(int x, int y) {
  myFiles.loadBitmap(x, y, 54, 54, "upM.raw");  // up
}
void dnM(int x, int y) {
  myFiles.loadBitmap(x, y, 54, 54, "downM.raw");  // down
}
void myTime(int x) {
  myGLCD.print("Hour", x, 293);
  myGLCD.print("Minute", x + 186, 293);
}

void setup() {
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawLine(0, 450, 799, 450); // on footer
  myFiles.loadBitmap(376, 426, 48, 48, "schIconL.raw");  // footer home button
  myFiles.loadBitmap(0, 0, 307, 59, "schPwI.raw");
  myGLCD.drawLine(71, 54, 799, 54); // under header
  // grid for schedule
  myGLCD.drawLine(0, 259, 799, 259); //
  myGLCD.drawLine(0, 414, 799, 414); //
  myGLCD.drawLine(400, 259, 400, 414); //
  upM(116, 271);
  dnM(116, 352);
  upM(321, 271);
  dnM(321, 352);
  upM(516, 271);
  dnM(516, 352);
  upM(721, 271);
  dnM(721, 352);
  myGLCD.setColor(255, 255, 255);
  myGLCD.setFont(BigFont);
  myGLCD.print("Start Time", 125, 232);
  myGLCD.print("Stop Time", 533, 232);

  myTime(26);
  myTime(426);
}
void loop() {
}

Regarding what guix said about IDE version, he is absolutely right!! And this is why:-

Original version in IDE 1.0.6 sketch size 26,100 bytes Optimised version in V1.0.6 26,084 bytes
Original version in IDE 1.5.8 sketch size 21,882 bytes Optimised version in V1.5.8 21,820 bytes

You can make most efficiency savings when you are using strings of text repeatedly, that is why the functions I chose made savings, whereas the functions you chose did not. (Over simplified I know, but in essence I am right before the experts come and jump all over me!!)

Regards,

Graham

  myFiles.loadBitmap(376, 426, 48, 48, "schIconL.raw");  // footer home button

See that string literal? It takes space in SRAM. Comment out this line of code, and you use less SRAM.

I'm new to all this so I have no idea if I'm using strings or dynamic memory. There are about 24 different screens in the GUI and it has sliders with a high and low setting so that took a lot of code. It's all very inefficient but it works well and that's what matters in the end, at least to me. If I get everything I want on this board its a huge success. :slight_smile:

IDE 1.5.8 never worked with my sketch so I always switched back and forth when working on Due or Mega. I just downloaded the nightly build which when installed shows up as 1.6.0 but has option for Due board. I complied and yes it did save a lot of space. Before this I altered the UTFT library cpp and h file and removed all instances of the display and controller types except the one I need, this dropped the sketch from 245,104 to 221,292, huge. Now after the switch to the better IDE it went down to 205,400. :slight_smile: If I get desperate I'll remove letters from fonts I don't use. :wink:

This IDE gives more info at the bottom, tells me global variables use 5,309 bytes (64%) of dynamic memory, leaving 2,883 bytes for local variables. Maximum is 8,192 bytes. Do I have much room to play with there? To me it sounds like I do.

Graham thanks for giving me that example, I guess understanding why your changes saved space and mine added space is for another day. :slight_smile: That's a very useful example, I use the up/down images maybe 40 times so I will change them all to that. I'll also do that to other images if I need to. I think I'll make it now though with the savings I just got.

I'll have to spend some time one week and read up on how the memory is used.

So does the code you post actually compile for you? I see you are calling the SdFat library, for me to compile it I have to add tinyFat library. I would love to change to the SdFat library so I can use larger memory cards as they are easier to get.

EDIT: Just remembered you use the Due and altered SdFat library, it won't work for me will it?

PaulS:

  myFiles.loadBitmap(376, 426, 48, 48, "schIconL.raw");  // footer home button

See that string literal? It takes space in SRAM. Comment out this line of code, and you use less SRAM.

So doing the changes Graham mentions will help there as well. I would have thought that line of code would only effect the flash memory.

robsworld78:
So does the code you post actually compile for you? I see you are calling the SdFat library, for me to compile it I have to add tinyFat library. I would love to change to the SdFat library so I can use larger memory cards as they are easier to get.

EDIT: Just remembered you use the Due and altered SdFat library, it won't work for me will it?

Yes it does compile. I gave up on tinyFAT eons ago, purely because I want my sketches to work on MEGA and DUE without modification! Also who wants to mess about with 2GB FAT16 and no folders? And it is actually modified UTFT_tinyFAT. Soon to be renamed, UTFT_SdRaw!

Regards,

Graham

robsworld78:
If I get desperate I'll remove letters from fonts I don't use. :wink:

No you won't. That would just be asking for whole heap of trouble! :stuck_out_tongue:

Graham

Changing lines or even removing a line could increase or decrease the total size. The compiler makes many decisions during optimization and the outcome is hard to predict.

The use of 5,309 bytes (64%) of dynamic memory, leaving 2,883 bytes free should normally be enough. But perhaps you use many String objects, or buffers are created in the libraries.

Why does 1.5.8 not work ? I'm using 1.5.8 with my Mega board, and I wonder when that would become a problem.

Test with my sketch (flash size, ram size):
1.5.8 BETA : 53.034, 2034
The -fira-loop-pressure shrinks flash to 52.930, the -flto option causes linker error.
Nightly Build (1.6.0) : 53.160, 2036
The -fira-loop-pressure shrinks flash to 53.054, the -flto option causes linker error.

My conclusion is that the Nightly Build of today increases both flash and ram size.

I get all kinds of errors when trying to use 1.5.8. First the UTFT default fonts are red flagged. I download them from the site, and copy and paste the code from it into the defaultfonts.c file and do that to the others to and then it will work. Then it gives errors for libraries, it doesn't like the Time library. So I download the newest version of that but it doesn't help. I'm ok with 1.6.0, its definitely doing better than 1.0.6.

Graham, could you post a copy of your modified libraries that get the SdFat library working with UTFT for the mega?

I forgot about this and tried that file you posted a couple months ago but it doesn’t work with the mega.

robsworld78:
I get all kinds of errors when trying to use 1.5.8. First the UTFT default fonts are red flagged. I download them from the site, and copy and paste the code from it into the defaultfonts.c file and do that to the others to and then it will work. Then it gives errors for libraries, it doesn't like the Time library. So I download the newest version of that but it doesn't help. I'm ok with 1.6.0, its definitely doing better than 1.0.6.

There were some changes with IDE 1.5.7. Have you got the updated versions of Henning's UTFT libraries? That should fix all your UTFT problems.......

Graham

PS.... I use it with MEGA and DUE, why didn't it work for you?

Yes I'm using the newest library, not sure on 1.5.8 it has always done that to me. It'll be nice not to have to switch now for Due or Mega.

Not sure why that file you posted a couple months ago doesn't work, its giving errors when compiling. I always assumed that your modified version was only for the Due so when I continued with the mega I never even tried your file, that's why I forgot about it till you posted that code above.

I didn't give a good try on the mega as I assumed it was only for the due, I'll play around with it tonight.

I was able to getting it working and wow it loads really quick. :slight_smile: Thanks again for it.

But there’s a problem. Very strange one. When I first attempted the sketch you optimized for me the screen would light up, show a couple images and restart and kept doing this really fast. So I commented out the images in the setup and it fired up perfectly. Then I added one of the images in the setup and again it worked, then added the other image and keeps restarting. So I try some other images but they all do the same thing. Then I add the same images that already work over and over and it always works.

Then I realize those are small images working so I start loading small images and it always works, as soon as I try a larger image it will restart it self.

I attached the sketch I’m playing with, notice in the setup how each image is getting larger, it works till the commented out images, those are too big. Everything uncommented will load no problem?

Any ideas why this might be?

#include <UTFT.h>
#include <SdFat.h>
#include <UTFT_tinyFAT.h>
extern uint8_t BigFont[];

UTFT myGLCD(CTE50, 38, 39, 40, 41);
UTFT_tinyFAT myFiles(&myGLCD);

const uint8_t chipSelect = SS;
SdFat sd;

int screenBrightPin = 8; // pwm pin for the LCD backlight
byte backLight = 255;  // startup brightness to 100%

void upM(int x, int y) {
  myFiles.loadBitmap(x, y, 54, 54, "upM.raw");  // up
}
void dnM(int x, int y) {
  myFiles.loadBitmap(x, y, 54, 54, "downM.raw");  // down
}
void myTime(int x) {
  myGLCD.print("Hour", x, 293);
  myGLCD.print("Minute", x + 186, 293);
}
void images()
{
  myFiles.loadBitmap(79, 81, 488, 21, "pwLabel1.raw");
  myFiles.loadBitmap(79, 250, 488, 21, "pwLabel2.raw");
  myFiles.loadBitmap(664, 67, 123, 20, "pwLabel3.raw");
  myFiles.loadBitmap(680, 121, 88, 132, "pwPwrOn.raw");
  myFiles.loadBitmap(680, 298, 88, 132, "pwPwrOff.raw");
  
}
void setup() {
  
  Serial.begin(9600);
  myGLCD.InitLCD(LANDSCAPE);
  
  myGLCD.clrScr();
  if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();
  
  pinMode(screenBrightPin, OUTPUT);
  
  analogWrite(screenBrightPin, backLight); // turn up screen brightness right away
  
  myGLCD.setFont(BigFont);
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawLine(0, 450, 799, 450); // on footer
  
  myFiles.loadBitmap(376, 426, 48, 48, "schIconL.raw");  // footer home button
  myFiles.loadBitmap(250, 250, 96, 96, "pwCo2LO.raw");  // footer home button
  myFiles.loadBitmap(352, 250, 96, 96, "pwAux2LO.raw");  // footer home button
  myFiles.loadBitmap(250, 350, 96, 96, "pwAux1LO.raw");  // footer home button
  myFiles.loadBitmap(0, 0, 193, 59, "pwIcoL.raw");  // footer home button
  myFiles.loadBitmap(50, 0, 125, 125, "volOff.raw");  // footer home button
  myFiles.loadBitmap(150, 0, 191, 59, "setIcon.raw");  // footer home button
//  myFiles.loadBitmap(350, 0, 249, 59, "liteIcoL.raw");  // footer home button
//  myFiles.loadBitmap(50, 0, 250, 250, "feedingL.raw");  // footer home button
//  myFiles.loadBitmap(0, 0, 307, 59, "schPwI.raw");
 // images();
  myGLCD.drawLine(71, 54, 799, 54); // under header
  // grid for schedule
  myGLCD.drawLine(0, 259, 799, 259); //
  myGLCD.drawLine(0, 414, 799, 414); //
  myGLCD.drawLine(400, 259, 400, 414); //
  upM(116, 271);
  dnM(116, 352);
  upM(321, 271);
  dnM(321, 352);
  upM(516, 271);
  dnM(516, 352);
  upM(721, 271);
  dnM(721, 352);
  myGLCD.setColor(255, 255, 255);
  myGLCD.setFont(BigFont);
  myGLCD.print("Start Time", 125, 232);
  myGLCD.print("Stop Time", 533, 232);

  myTime(26);
  myTime(426);
}
void loop() {
    Serial.print("looping  ");
     Serial.print("\n");
}

I’ve determined its because of a smaller screen. If I’m outside 220x320 it will reset. I’m trying all kinds of combinations in your UTFT_tinyfat.cpp file, I’m have a feeling its because of these lines but what should they be is the question, lol.

	char buffer[32*sx];

		result=16*sx;
		if (_UTFT->orient==PORTRAIT)

		for(int n=0;n<sy;n+=16)

			result=dataFile.read(&buffer,32*sx);
			if (_UTFT->orient==PORTRAIT)

EDIT: I should also mention the placement of images is correct.

Hi Rob,

Ops, you are quite right! :stuck_out_tongue:

The MEGA with its limited amount of free SRAM is the problem, so if you are trying to draw a 800480 image, that would equate to 80032 = 25,600 bytes of buffer........

I am only guessing here since I don't know how much free RAM your sketch will have..... but swap 32 for 8, and 16 for 4 ..... if still no dice, try 6 and 3...... or 4 and 2 ..... but the speed gains come from biggest buffer size.

There is an updated version in the pipeline that will be auto sizing on the buffer.... but for now, you can adjust it yourself to make it work.

Best wishes,

Graham

Edit: it is the 'X' size that is multiplied.... so 488*8=3904, that should be fine?

On my DUE, I have tried 96* !! , sometimes crashes, sometimes works, but when it works, that is fast!! :o

If you were here I would give you a big juicy Christmas kiss, lol. :kissing: I love you man! This is by far the best gift I’ll get for Christmas. :slight_smile:

My mega is on steroids, its awesome!

I had to go down to 2 and 1 to get it to work on all the pages. Now that its crazy fast I’m going to remove my large images which I had to make before because to many images on the SD card slowed it down even more. Maybe after those changes I can move the number to 6 3 or something.

If you’re using the original UTFT library there’s a better one. I got a modified version quite some time ago which removed delays between images. I know that’s not an issue now but it also made big improvements on filling rectangles and clearing the screen. While setting up your library I went back to the original just to be sure I’m working with good stuff and now have gone back to the modified and my screen clears so much quicker, I forgot how slow the original library was.

I attached the file if you want to give it a try, my screen clears almost instantly.

UTFT_optimised.zip (58.9 KB)