Why is my pretty small sketch taking up so much program space(atmega328p-au)

I am making an Arduino smartwatch with "0.49" oled display and the simple watch code I created takes up 99% of program space. But I have seen other smartwatch codes with more variables, with more functions ,way, more lines of code and so much more with the exact same chip I am using. I want to add more things but I can't because of the limitations of space. Maybe it's a bad bootloader?

code:

#include <Wire.h>
#include "RTClib.h"
#include <Adafruit_GFX.h>
#include <U8g2lib.h>

U8G2_SSD1306_64X32_1F_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
RTC_DS1307 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

#include <Adafruit_SSD1306.h>
#define OLED_WIDTH 64 // OLED display width, in pixels
#define OLED_HEIGHT 32 // OLED display height, in pixels
#define OLED_ADDR 0x3C
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

byte mode1 = 1;
byte mode2 = 2;
byte mode3 = 3;
byte mode4 = 4;
byte mode5 = 5;
const byte button1 = 2;
const byte button2 = 3;
const byte button3 = 4;
int state = HIGH; // the current state of the output pin
int reading; // the current reading from the input pin
int previous = LOW;

int const LONG_PRESS_TIME = 3000; // 1000 milliseconds
// Variables will change:
int lastState = LOW; // the previous state from the input pin
int currentState; // the current reading from the input pin
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;// the previous reading from the input pin
bool isPressing = false;
bool isLongDetected = false;
byte counter1 = 0;

int ThermistorPin = A0;//thermister variables
int Vo;
float R1 = 10000;
float logR2, R2, T;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;

unsigned long time = 0; // the last time the output pin was toggled
unsigned long debounce = 200UL; // the debounce time, increase if the output flickers

const int SHORT_PRESS_TIME = 500; // 500 milliseconds

// Variables will change:
int lastState1 = LOW; // the previous state from the input pin
int currentState1; // the current reading from the input pin
unsigned long pressedTime1 = 0;
unsigned long releasedTime1 = 0;

byte counter2 = 0;

void setup() {
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay();
u8g2.begin();

Serial.begin(57600);

#ifndef ESP8266
while (!Serial); // wait for serial port to connect. Needed for native USB
#endif

if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}

if (! rtc.isrunning()) {
Serial.println("RTC is NOT running, let's set the time!");
// When time needs to be set on a new device, or after a power loss, the
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(DATE), F(TIME)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}

// When time needs to be re-set on a previously configured device, the
// following line sets the RTC to the date & time this sketch was compiled
// rtc.adjust(DateTime(F(DATE), F(TIME)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

pinMode(A0, INPUT);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);

u8g2.clearBuffer(); // clear the internal memory
u8g2.setFont( u8g2_font_profont10_mf); // choose a suitable font
u8g2.drawStr(0, 15, "LUCAS"); // write something to the internal memory
u8g2.drawStr(0, 30, "ELECTRONICS");
u8g2.sendBuffer(); // transfer internal memory to the display
delay(3000);

}

void loop() {
DateTime now = rtc.now();

/* Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();

Serial.println();*/

u8g2.clearBuffer();
u8g2.setFont(u8g2_font_t0_11_tf);
u8g2.drawStr(0, 10, "T"); //time display
u8g2.setCursor(7, 10);
u8g2.print(now.hour(), DEC);
u8g2.drawStr(17, 10, ":");
u8g2.setCursor(21, 10);
u8g2.print(now.minute(), DEC);
u8g2.drawStr(31, 10, ":");
u8g2.setCursor(35, 10);
u8g2.print(now.second(), DEC);
u8g2.drawStr(0, 20, "D"); //date display
u8g2.setCursor(7, 20);
u8g2.print(now.day(), DEC);
u8g2.drawStr(17, 20, ":");
u8g2.setCursor(21, 20);
u8g2.print(now.month(), DEC);
u8g2.drawStr(31, 20, ":");
u8g2.setCursor(35, 20);
u8g2.print(now.year(), DEC);
u8g2.drawStr(0, 30, "TEMP"); //temp display
u8g2.setCursor(25, 30);
u8g2.print(T);
u8g2.drawStr(55, 30, "F");
u8g2.sendBuffer();

Vo = analogRead(ThermistorPin);
R2 = R1 * (1023.0 / (float)Vo - 1.0);
logR2 = log(R2);
T = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
T = T - 273.15;
T = (T * 9.0) / 5.0 + 32.0;

// Serial.print("Temperature: ");
// Serial.print(T);
// Serial.println(" F");

currentState = digitalRead(button1);

if (lastState == HIGH && currentState == LOW) { // button is pressed
pressedTime = millis();
isPressing = true;
isLongDetected = false;
} else if (lastState == LOW && currentState == HIGH) { // button is released
isPressing = false;
releasedTime = millis();

long pressDuration = releasedTime - pressedTime;

if ( pressDuration < SHORT_PRESS_TIME )
  Serial.println("A short press is detected");

}

if (isPressing == true && isLongDetected == false) {
long pressDuration = millis() - pressedTime;

if ( pressDuration > LONG_PRESS_TIME )
{
  counter1 += 1;


  isLongDetected = true;
}

}

lastState = currentState;

if (counter1 == 1) {
time_change();
}
if (counter1 == 2) {
counter1 = 0 ;
}
}

void time_change() {

DateTime now = rtc.now();

currentState1 = digitalRead(button3);

if (lastState1 == HIGH && currentState1 == LOW) // button is pressed
pressedTime1 = millis();
else if (lastState1 == LOW && currentState1 == HIGH) { // button is released
releasedTime1 = millis();

long pressDuration1 = releasedTime1 - pressedTime1;

if ( pressDuration1 < SHORT_PRESS_TIME )
  counter2 += 1;
// Serial.print("working");

}
lastState1 = currentState1;

if (counter2 == 0) {

u8g2.clearBuffer();
u8g2.setFont(u8g2_font_t0_11_tf);
u8g2.setCursor(7, 10);
u8g2.print(now.hour(), DEC);
u8g2.clearBuffer();
delay(250);
u8g2.drawStr(0, 10, "T");  //time display
u8g2.drawStr(17, 10, ":");
u8g2.setCursor(21, 10);
u8g2.print(now.minute(), DEC);
u8g2.drawStr(31, 10, ":");
u8g2.setCursor(35, 10);
u8g2.print(now.second(), DEC);
u8g2.drawStr(0, 20, "D"); //date display
u8g2.setCursor(7, 20);
u8g2.print(now.day(), DEC);
u8g2.drawStr(17, 20, ":");
u8g2.setCursor(21, 20);
u8g2.print(now.month(), DEC);
u8g2.drawStr(31, 20, ":");
u8g2.setCursor(35, 20);
u8g2.print(now.year(), DEC);
u8g2.drawStr(0, 30, "TEMP"); //temp display
u8g2.setCursor(25, 30);
u8g2.print(T);
u8g2.drawStr(55, 30, "F");
u8g2.sendBuffer();

}
if (counter2 == 0 && digitalRead(button2) == LOW) {
short h = now.hour();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), h += 1, now.minute(), now.second()));

}

if (counter2 == 1) {

u8g2.clearBuffer();
u8g2.setFont(u8g2_font_t0_11_tf);
u8g2.setCursor(21, 10);
u8g2.print(now.minute(), DEC);
u8g2.clearBuffer();
delay(250);
u8g2.drawStr(0, 10, "T");//time display
u8g2.setCursor(7, 10);
u8g2.print(now.hour(), DEC);
u8g2.drawStr(17, 10, ":");
u8g2.drawStr(31, 10, ":");
u8g2.setCursor(35, 10);
u8g2.print(now.second(), DEC);
u8g2.drawStr(0, 20, "D"); //date display
u8g2.setCursor(7, 20);
u8g2.print(now.day(), DEC);
u8g2.drawStr(17, 20, ":");
u8g2.setCursor(21, 20);
u8g2.print(now.month(), DEC);
u8g2.drawStr(31, 20, ":");
u8g2.setCursor(35, 20);
u8g2.print(now.year(), DEC);
u8g2.drawStr(0, 30, "TEMP"); //temp display
u8g2.setCursor(25, 30);
u8g2.print(T);
u8g2.drawStr(55, 30, "F");
u8g2.sendBuffer();

}
if (counter2 == 1 && digitalRead(button2) == LOW) {
short m = now.minute();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), m += 1, now.second()));

}

if (counter2 == 2) {

u8g2.clearBuffer();
u8g2.setFont(u8g2_font_t0_11_tf);
u8g2.setCursor(35, 10);
u8g2.print(now.second(), DEC);
delay(250);
u8g2.clearBuffer();
u8g2.drawStr(0, 10, "T");  //time display
u8g2.setCursor(7, 10);
u8g2.print(now.hour(), DEC);
u8g2.drawStr(17, 10, ":");
u8g2.setCursor(21, 10);
u8g2.print(now.minute(), DEC);
u8g2.drawStr(31, 10, ":");
u8g2.drawStr(0, 20, "D"); //date display
u8g2.setCursor(7, 20);
u8g2.print(now.day(), DEC);
u8g2.drawStr(17, 20, ":");
u8g2.setCursor(21, 20);
u8g2.print(now.month(), DEC);
u8g2.drawStr(31, 20, ":");
u8g2.setCursor(35, 20);
u8g2.print(now.year(), DEC);
u8g2.drawStr(0, 30, "TEMP"); //temp display
u8g2.setCursor(25, 30);
u8g2.print(T);
u8g2.drawStr(55, 30, "F");
u8g2.sendBuffer();

}
if (counter2 == 2 && digitalRead(button2) == LOW) {
short s = now.second();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), s += 1 ));

}

if (counter2 == 3) {

u8g2.clearBuffer();
u8g2.setFont(u8g2_font_t0_11_tf);
u8g2.setCursor(35, 10);
u8g2.print(now.second(), DEC);
delay(250);
u8g2.clearBuffer();
u8g2.drawStr(0, 10, "T");  //time display
u8g2.setCursor(7, 10);
u8g2.print(now.hour(), DEC);
u8g2.drawStr(17, 10, ":");
u8g2.setCursor(21, 10);
u8g2.print(now.minute(), DEC);
u8g2.drawStr(31, 10, ":");
u8g2.drawStr(0, 20, "D"); //date display
u8g2.setCursor(7, 20);
u8g2.print(now.day(), DEC);
u8g2.drawStr(17, 20, ":");
u8g2.setCursor(21, 20);
u8g2.print(now.month(), DEC);
u8g2.drawStr(31, 20, ":");
u8g2.setCursor(35, 20);
u8g2.print(now.year(), DEC);
u8g2.drawStr(0, 30, "TEMP"); //temp display
u8g2.setCursor(25, 30);
u8g2.print(T);
u8g2.drawStr(55, 30, "F");
u8g2.sendBuffer();

}
if (counter2 == 3 && digitalRead(button2) == LOW) {
short s = now.second();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), s += 1 ));

}
if (counter2 == 4) {

u8g2.clearBuffer();
u8g2.setFont(u8g2_font_t0_11_tf);
u8g2.setCursor(7, 20);
u8g2.print(now.day(), DEC);
delay(250);
u8g2.clearBuffer();
u8g2.drawStr(0, 10, "T");  //time display
u8g2.setCursor(7, 10);
u8g2.print(now.hour(), DEC);
u8g2.drawStr(17, 10, ":");
u8g2.setCursor(21, 10);
u8g2.print(now.minute(), DEC);
u8g2.drawStr(31, 10, ":");
u8g2.setCursor(35, 10);
u8g2.print(now.second(), DEC);
u8g2.drawStr(0, 20, "D"); //date display
u8g2.drawStr(17, 20, ":");
u8g2.setCursor(21, 20);
u8g2.print(now.month(), DEC);
u8g2.drawStr(31, 20, ":");
u8g2.setCursor(35, 20);
u8g2.print(now.year(), DEC);
u8g2.drawStr(0, 30, "TEMP"); //temp display
u8g2.setCursor(25, 30);
u8g2.print(T);
u8g2.drawStr(55, 30, "F");
u8g2.sendBuffer();

}
if (counter2 == 4 && digitalRead(button2) == LOW) {
short d = now.day();
rtc.adjust(DateTime(now.year(), now.month(), d += 1, now.hour(), now.minute(), now.second() ));

}
if (counter2 == 5) {

u8g2.clearBuffer();
u8g2.setFont(u8g2_font_t0_11_tf);
u8g2.setCursor(21, 20);
u8g2.print(now.month(), DEC);
delay(250);
u8g2.clearBuffer();
u8g2.drawStr(0, 10, "T");  //time display
u8g2.setCursor(7, 10);
u8g2.print(now.hour(), DEC);
u8g2.drawStr(17, 10, ":");
u8g2.setCursor(21, 10);
u8g2.print(now.minute(), DEC);
u8g2.drawStr(31, 10, ":");
u8g2.setCursor(35, 10);
u8g2.print(now.second(), DEC);
u8g2.drawStr(0, 20, "D"); //date display
u8g2.setCursor(7, 20);
u8g2.print(now.day(), DEC);
u8g2.drawStr(17, 20, ":");
u8g2.drawStr(31, 20, ":");
u8g2.setCursor(35, 20);
u8g2.print(now.year(), DEC);
u8g2.drawStr(0, 30, "TEMP"); //temp display
u8g2.setCursor(25, 30);
u8g2.print(T);
u8g2.drawStr(55, 30, "F");
u8g2.sendBuffer();

}
if (counter2 == 5 && digitalRead(button2) == LOW) {
short p = now.month();
rtc.adjust(DateTime(now.year(), p += 1, now.day(), now.hour(), now.minute(), now.second() ));

}
if (counter2 == 6) {

u8g2.clearBuffer();
u8g2.setFont(u8g2_font_t0_11_tf);
u8g2.setCursor(35, 20);
u8g2.print(now.year(), DEC);
delay(250);
u8g2.clearBuffer();
u8g2.drawStr(0, 10, "T");  //time display
u8g2.setCursor(7, 10);
u8g2.print(now.hour(), DEC);
u8g2.drawStr(17, 10, ":");
u8g2.setCursor(21, 10);
u8g2.print(now.minute(), DEC);
u8g2.drawStr(31, 10, ":");
u8g2.setCursor(35, 10);
u8g2.print(now.second(), DEC);
u8g2.drawStr(0, 20, "D"); //date display
u8g2.setCursor(7, 20);
u8g2.print(now.day(), DEC);
u8g2.drawStr(17, 20, ":");
u8g2.setCursor(21, 20);
u8g2.print(now.month(), DEC);
u8g2.drawStr(31, 20, ":");
u8g2.drawStr(0, 30, "TEMP"); //temp display
u8g2.setCursor(25, 30);
u8g2.print(T);
u8g2.drawStr(55, 30, "F");
u8g2.sendBuffer();

}
if (counter2 == 6 && digitalRead(button2) == LOW) {
short y = now.year();
rtc.adjust(DateTime(y += 1, now.month(), now.day(), now.hour(), now.minute(), now.second()));

}

if (counter2 == 7) {
counter2 = 0;
}

}

complier message:

"C:\Users\user\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\Users\user\AppData\Local\Temp\arduino_build_233508/watch_code_v2.ino.elf"
Sketch uses 31588 bytes (12%) of program storage space. Maximum is 253952 bytes.
Global variables use 1219 bytes (14%) of dynamic memory, leaving 6973 bytes for local variables. Maximum is 8192 bytes.

I will really appreciate if someone could help me.

Because

Please remember to use code tags when posting code

A 328? :open_mouth:

It looks to me like your code would benefit from some refactoring

1 Like

ok, so it is the libraries that are the problems?

And the refactoring.

1 Like

sorry not 253952 bytes

what is refactoring?

"C:\Users\user\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\Users\user\AppData\Local\Temp\arduino_build_233508/watch_code_v2.ino.elf"
Sketch uses 30624 bytes (99%) of program storage space. Maximum is 30720 bytes.
Global variables use 1219 bytes of dynamic memory.

This is the complier message.

Are you using two displays? Using U8g2 and Adafruit_SSD1306 at the same time would not be advisable, and will take a huge amount of the memory (both program memory and ram).

1 Like

It means making changes to your code which don't change the way it works, but make it more efficient, readable or maintainable.

1 Like

No, I am only using one but I am using both libraries because one is for the text (U8g2) and the other for future bitmap images I will want to use. I don't think you can do bitmap images with theU8g2 library.

Ok, thanks.

I didn't check if this is correct, but at least you could then use the SSD1306 for both text & graphics? Having 2 libraries for the same display doesn't make sense.

1 Like

I think I will get rid of the Adafruit_SSD1306 library.

But the minimum size of text with the Adafruit_SSD1306 is to big to fit what I want to on the "0.49" oled display. So that is why I am using the U8g2 library.

I think you need to dive a little deeper into what you can do with each library. I'm quite sure you will need only one of both.

1 Like

U8g2 has functions for bitmaps.

Do not use both libraries, at the moment U8g2 is allocating 1024 bytes for a display buffer, and when the code runs the Adafruit library will allocate an additional 1024 bytes for its display buffer, which will consume the entire available ram of the atmega328. There will also be countless conflicts between the libraries when trying to drive the same display.

1 Like

Ok, thank you very much for helping me with this.

Use a different font.

1 Like

SSD1306 is a monochrome display, although you can get displays where different portions of the screen are different (fixed) colors.

1 Like

Sorry, all, I got confused with another topic!

1 Like