No way this file is too big

This is poppycock:

Here’s the code:

#include <Arduino.h>
#include "Time.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Fonts/FreeMono9pt7b.h"
#include "Fonts/FreeMonoBold9pt7b.h"
#include "Fonts/FreeMonoBoldOblique9pt7b.h"
#include "Fonts/FreeMonoOblique9pt7b.h"
#include "Fonts/FreeSans9pt7b.h"
#include "Fonts/FreeSansBold9pt7b.h"
#include "Fonts/FreeSansBoldOblique9pt7b.h"
#include "Fonts/FreeSansOblique9pt7b.h"
#include "Fonts/FreeSerif9pt7b.h"
#include "Fonts/FreeSerifBold9pt7b.h"
#include "Fonts/FreeSerifBoldItalic9pt7b.h"
#include "Fonts/FreeSerifItalic9pt7b.h"
#include "Fonts/Org_01.h"
#include "Fonts/Picopixel.h"
#include "Fonts/Tiny3x3a2pt7b.h"
#include "Fonts/TomThumb.h"

#include "Adafruit_SSD1306.h"

#define PAUSE 3000 // How long to delay?

#define LED01 2
#define LED02 3
#define LED03 4
#define LED04 5
#define LED05 6

int LEDone = LED01;
int LEDtwo = LED02;
int LEDthree = LED03;
int LEDfour = LED04;
int LEDfive = LED05;

const int BZR01 = 8;
const int BZR02 = 9;
const int BZR03 = 10;
const int BZR04 = 11;
const int BZR05 = 12;

long randomNumber = 0L; // Use the "L" to tell compiler it's a long data type, not an int.

Adafruit_SSD1306 display(128, 64, &Wire, 8); //Declaring the display name (display)

// the setup routine runs once when you press reset:
void setup()
{

  display.setFont(&Org_01);
}

void loop()
{

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Start the OLED display
  display.clearDisplay();
  display.display();
  display.setFont(&Org_01);
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(1, 12);
  display.setFont(&Org_01);
  display.print("Org_01   ");
  display.setFont(&FreeMono9pt7b);
  display.print("FreeMono9pt7b   ");
  display.setFont(&FreeMonoBold9pt7b);
  display.print("FreeMonoBold9pt7b   ");
  display.setFont(&FreeMonoBoldOblique9pt7b);
  display.print("FreeMonoBoldOblique9pt7b   ");
  display.setFont(&FreeMonoOblique9pt7b);
  display.print("FreeMonoOblique9pt7b   ");
  display.setFont(&FreeSans9pt7b);
  display.print("FreeSans9pt7b   ");
  display.setFont(&FreeSansBold9pt7b);
  display.print("FreeSansBold9pt7b   ");
  display.setFont(&FreeSansBoldOblique9pt7b);
  display.print("FreeSansBoldOblique9pt7b   ");
  display.setFont(&FreeSansOblique9pt7b);
  display.print("FreeSansOblique9pt7b   ");

  display.setFont(&FreeSerif9pt7b);
  display.print("FreeSerif9pt7b   ");
  display.setFont(&FreeSerifBold9pt7b);
  display.print("FreeSerifBold9pt7b   ");

  display.setFont(&FreeSerifItalic9pt7b);
  display.print("FreeSerifItalic9pt7b   ");
  display.setFont(&Org_01);
  display.print("Org_01");
  display.setFont(&FreeSerifBoldItalic9pt7b);
  display.print("FreeSerifBoldItalic9pt7b   ");
  display.setFont(&Picopixel);
  display.print("Picopixel   ");
  display.setFont(&Tiny3x3a2pt7b);
  display.print("Tiny3x3a2pt7b   ");
  display.setFont(&TomThumb);
  display.print("TomThumb   ");

  display.display();
}

You are exceeding the flash space of the Uno by 23.3% by compiling that firmware. The error message is right – the uno only has 32kBytes of flash, your program compiles to ~39KByte.

Reduce the amount of needed flash space by not including every possible font (I count 15?), as one possibility.

I’m trying to see all the GFX fonts.

It’s 103 lines. It’s 3kb.
How do we get to 32kb?

That was a joke right? :smiley:

The length of your sketch file, in your case really ~3kByte, is not 1:1 the size of the compiled program. The compiled binary result from the compiler is uploaded to the board, not your verbatim C++ text file!

The firmware size (flash usage) is dependent on the size of the compiled functions (aka, the resulting AVR microcode here) and the initialization data of variables, if they are initialized. Analogue, the RAM usage of the firmware is dependent on the size all mutable variables.

The size of the compiled functions depend on the complexity of the function. The more instructions, the longer the compiled result. If the function calls other functions (e.g., from the C library or a library), that function will have to included in the final result too, increasing the size.

The size of the initialized variables is dependent on that variable’s size. E.g, you see that by including FreeSerifBold9pt7b.h you get two variables which are initialized with approx 1200 byte values, so they will take 1200 bytes. That was this one font. You include 15. If each takes the same space, that’s ~18kBytes of flash just for pure font data.

Also note that your file is not the only file that gets compiled: You’re leaving out the entire Arduino framework files, library code and AVR standard C-library that is used by your code (and its dependencies).

I can write a piece of code for the Uno that goes

#include <Arduino.h>

/* uninitialized buffer */
uint8_t myBuffer[4 * 1024]; 
void setup() { Serial.print(myBuffer, sizeof(myBuffer)); }
void loop() { }

and the compilation result of that single file will allocate 4 kBytes of RAM, instantly exceeding the 2kBytes which are available. Analogue to flash.

Please read through Analyze your firmware footprint with PlatformIO: Part 1. Intro and basic analysis | PlatformIO Labs.

PlatformIO can also do memory usage analysis – but for that, you have to get the firmware to compile first. You can add board_upload.maximum_size = 64000 in the platformio.ini to force compilation. Then you can use the “Inspect” project task to get to the memory analyzer of PlatformIO.

image

1 Like

I highly recommend you have a play with the godbolt compiler explorer https://godbolt.org/ It shows you exactly how a function is compiled into microcode (and thus the resulting size). Same goes for variables.

A video on compiler theory should also help: KEYNOTE: What Everyone Should Know About How Amazing Compilers Are - Matt Godbolt [C++ on Sea 2019] - YouTube

2 Likes

Thanks @maxgerhardt, excellent video.

Cheers,
Norm.

1 Like

So PIO doesn’t want to do a file that big, but you force it?
It simply wouldn’t be able to fit into a smaller chip, so I guess it’s an academic exercise or useful to people who operate a layer behind this one.

Thank you very much. I’ll try to watch the video, but I am saturated.
I might take a few weeks off.
I’m putting too much pressure on myself.

I’ll upgrade the memory of my Linux machine and see if I can get Arduino to work. Some of the Arduino scripts wouldn’t compile for declaration problems, so maybe Arduino IDE can compile it. But that’s another can of worms if Arduino won’t connect with a device. I’m not going to bother figuring out how to do it. It will go back to the closet.
I have to ration my frustration so I don’t quit.

XP could run a 1980s robot running in Windows NT simulation.
It was like NT without the constant failure whenever anything changed.
Plug and play.

Only three lines actually fit on the 1306 OLED.

Whilst your code might be only 3kb, you’re not taking into account

  1. how much extra is needed by the Arduino core and libraries (Arduino.h, Wire.h, etc)
  2. how much extra is needed by the 3rd party libraries you are using (Adafruit_GFX.h, Adafruit_SSD1306.h)
  3. how much extra is needed by all the fonts you are including.

The Atmega328 on the Arduino Uno only has 32kb of program memory space… and fonts take up a lot of space. You can usually only use a couple in a program that has any real complexity to it… and here you are using no less than 16. You need to get rid of some of the fonts, and then try again. Just comment out a couple of the includes and the corresponding setFont/print statements, and you’ll be fine. Or, use a different board, i.e. use one of the ESP8266s you have already… then you can have a program up to 1MB in size.

Because you need to show a couple lines - say only do two, then have a delay of say 5 seconds so you have time to look at them, and then .clear() the display, .setCursor() back at the top of the top of the screen, and then show the next font samples. Repeat, repeat, repeat. Don’t take any shortcuts.

I wanted PIO to force to generate the .elf file because only with that you can analyze the memory usage. When there’s a “overflowed flash by …” error, the elf file won’t be built for analysis. It will never fit and execute on the real processor, but that’s not the goal.

1 Like