Get more free space.

Hello. Im using this libraries:

#include <Wire.h>
#include "Adafruit_MCP23008.h"
#include "Adafruit_MCP23017.h"

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include <DS3231.h>

#include <IRremote.h>

And with this I have 45% space used.

What I had done:

in IRremote.h I have check only one protocol which I need.

But its possible to change something in other libraries to get more space?

Why do you need more space ?

What about the rest of your code ?

Do you use arrays and, if so, what range of values are stored and how are the arrays declared ?
Do you do much printing of text in your program ? If so then consider using the F() macro
Do all of your variables use appropriate data types such as byte for pin numbers rather than int, for instance ? Are unchanging variables declared as const ?

srnet:
Why do you need more space ?

With all my code I have 94% used space. But I need to write more functions. So I need more kb.. :slight_smile:

UKHeliBob:
What about the rest of your code ?

Do you use arrays and, if so, what range of values are stored and how are the arrays declared ?

No Im not using arrays.

Do you do much printing of text in your program ? If so then consider using the F() macro

Much printing.. Its difficult to say. 50/50. I will try F() macro. But, F() macro saves SRAM memory instead od FLASH, isnt it? I need more space on FLASH, not SRAM.

Do all of your variables use appropriate data types such as byte for pin numbers rather than int, for instance ?

After change from int to byte I have decrease used space of 1%, now its 93%.

Are unchanging variables declared as const ?

Yes.

Post your code. Perhaps someone will be able to see some refactoring you can do.

I think I can save some space if I will add arrays for this in void setup():

//6ch button
 mcp1.pinMode(0, INPUT);
 mcp1.pinMode(1, INPUT);
 mcp1.pinMode(2, INPUT);
 mcp1.pinMode(3, INPUT);
 mcp1.pinMode(4, INPUT);
 mcp1.pinMode(5, INPUT);
 mcp1.pinMode(6, INPUT);
 mcp1.pinMode(7, INPUT);

 //6ch led
 mcp1.pinMode(8, OUTPUT);
 mcp1.pinMode(9, OUTPUT);
 mcp1.pinMode(10, OUTPUT);
 mcp1.pinMode(11, OUTPUT);
 mcp1.pinMode(12, OUTPUT);
 mcp1.pinMode(13, OUTPUT);
 mcp1.pinMode(14, OUTPUT);
 mcp1.pinMode(15, OUTPUT);

 //selektor cyfrowy
 mcp2.pinMode(0, OUTPUT);
 mcp2.pinMode(1, OUTPUT);
 mcp2.pinMode(2, OUTPUT);
 mcp2.pinMode(3, OUTPUT);
 mcp2.pinMode(4, OUTPUT);
 mcp2.pinMode(5, OUTPUT);
 mcp2.pinMode(6, OUTPUT);
 mcp2.pinMode(7, OUTPUT);

 //selektor analogowy
 
 mcp3.pinMode(0, OUTPUT);
 mcp3.pinMode(1, OUTPUT);
 mcp3.pinMode(2, OUTPUT);
 mcp3.pinMode(3, OUTPUT);
 mcp3.pinMode(4, OUTPUT);
 mcp3.pinMode(5, OUTPUT);
 mcp3.pinMode(6, OUTPUT);
 mcp3.pinMode(7, OUTPUT);

 //pvc
 mcp4.pinMode(0, OUTPUT);
 mcp4.pinMode(1, OUTPUT);
 mcp4.pinMode(2, OUTPUT);
 mcp4.pinMode(3, OUTPUT);
 mcp4.pinMode(4, OUTPUT);
 mcp4.pinMode(5, OUTPUT);
 mcp4.pinMode(6, OUTPUT);
 mcp4.pinMode(7, OUTPUT);

about my code, I think that I cant change nothing to get more free space. Main problem is with all libraries which arent optymalize :

void PrintRTC()
{
  dt = clock.getDateTime();
  if (blokadaRTC == 0)
  {
    display.drawLine(74, 18, 128, 18, WHITE);
    display.fillRect(74, 0, 54, 8, WHITE);
    display.drawRect(74, 8, 54, 22, WHITE);
    display.setTextSize(1);
    display.setTextColor(BLACK, WHITE);
    display.setCursor(90, 1);
    display.print("DATE");
  }
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(77, 10);
  FillRTC();
  if (dt.hour < 10)
  {
    display.print("0");
  }
  display.print(dt.hour);
  display.print(":");
  if (dt.minute < 10)
  {
    display.print("0");
  }
  display.print(dt.minute);
  display.print(":");
  if (dt.second < 10)
  {
    display.print("0");
  }
  display.print(dt.second);

  display.setCursor(77, 20);
  if (dt.day < 10)
  {
    display.print("0");
  }
  display.print(dt.day);
  display.print(".");
  if (dt.month < 10)
  {
    display.print("0");
  }
  display.print(dt.month);
  display.print(".");
  display.print(dt.year - 2000);
  blokadaRTC = 1;
}

void PrintAnalog()
{
  if (blokadaAnalog == 0)
  {
    display.fillRect(0, 0, 54, 8, WHITE);
    display.drawRect(0, 8, 54, 22, WHITE);
    display.setTextSize(1);
    display.setTextColor(BLACK, WHITE);
    display.setCursor(4, 1);
    display.print(" ANALOG");
  }

  if (count == 1 && blokadaClearFillAnalog == 0)
  {
    ClearFillAnalog();
  }
  display.setTextSize(1);
  display.setTextColor(WHITE);
  FillAnalog();
  if (Analog == 1)
  {
    drawCentreString("DAC", 27, 15);
  }
  else if (Analog == 2)
  {
    drawCentreString("IN-2", 27, 15);
  }
  else if (Analog == 3)
  {
    drawCentreString("IN-3", 27, 15);;
  }
  else if (Analog == 4)
  {
    drawCentreString("IN-4", 27, 15);
  }
  else if (Analog == 5)
  {
    drawCentreString("IN-5", 27, 15);
  }
  else if (Analog == 6)
  {
    drawCentreString("VIDEO", 27, 15);
  }
  blokadaAnalog = 1;
}

void PrintDigital()
{
  if (blokadaDigital == 0)
  {
    display.fillRect(0, 35, 54, 9, WHITE);
    display.drawRect(0, 35, 54, 29, WHITE);
    display.setTextSize(1);
    display.setTextColor(BLACK, WHITE);
    display.setCursor(7, 36);
    display.print("DIGITAL");
  }
  if (count == 2 && blokadaClearFillDigital == 0)
  {
    ClearFillDigital();
  }
  display.setTextSize(1);
  display.setTextColor(WHITE);
  FillDigital();
  if (Digital == 1)
{
  drawCentreString("TV", 27, 50);
  }
  else if (Digital == 2)
{
  drawCentreString("XBOX", 27, 50);
  }
  else if (Digital == 3)
{
  drawCentreString("DVD", 27, 50);
  }
  else if (Digital == 4)
{
  drawCentreString("COAX", 27, 50);
  }
  else if (Digital == 5)
{
  drawCentreString("USB", 27, 50);
  }
  else if (Digital == 6)
{
  drawCentreString("BT", 27, 50);
  }

  blokadaDigital = 1;


void AnalogChange()
{
  if (Analog_change)
  {
    Analog_change = 0;

    if (Analog == 1)
    {
      mcp3.digitalWrite(5, HIGH);
      mcp1.digitalWrite(8, HIGH);
    }
    else
    {
      mcp3.digitalWrite(5, LOW);
      mcp1.digitalWrite(8, LOW);
    }

    if (Analog == 2)
    {
      mcp3.digitalWrite(4, HIGH);
      mcp1.digitalWrite(9, HIGH);
    }
    else
    {
      mcp3.digitalWrite(4, LOW);
      mcp1.digitalWrite(9, LOW);
    }

    if (Analog == 3)
    {
      mcp3.digitalWrite(3, HIGH);
      mcp1.digitalWrite(10, HIGH);
    }
    else
    {
      mcp3.digitalWrite(3, LOW);
      mcp1.digitalWrite(10, LOW);
    }

    if (Analog == 4)
    {
      mcp3.digitalWrite(2, HIGH);
      mcp1.digitalWrite(11, HIGH);
    }
    else
    {
      mcp3.digitalWrite(2, LOW);
      mcp1.digitalWrite(11, LOW);
    }
    if (Analog == 5)
    {
      mcp3.digitalWrite(1, HIGH);
      mcp1.digitalWrite(12, HIGH);
    }
    else
    {
      mcp3.digitalWrite(1, LOW);
      mcp1.digitalWrite(12, LOW);
    }
    if (Analog == 6)
    {
      mcp3.digitalWrite(0, HIGH);
      mcp1.digitalWrite(13, HIGH);
    }
    else
    {
      mcp3.digitalWrite(0, LOW);
      mcp1.digitalWrite(13, LOW);
    }
  }
}
}

First optimization:

for(byte lp=0;lp<8;p++)
   {
   mcp1.pinMode(lp, INPUT);
   mcp2.pinMode(lp, OUTPUT);
   mcp3.pinMode(lp, OUTPUT);
   mcp4.pinMode(lp, OUTPUT);
   }

Similarly, repeated lines like this:

    drawCentreString("DAC", 27, 15);

Can pull the string they're printing from an array and be done then with a single line of code.

wildbill:
First optimization:

for(byte lp=0;lp<8;p++)

{
  mcp1.pinMode(lp, INPUT);
  mcp2.pinMode(lp, OUTPUT);
  mcp3.pinMode(lp, OUTPUT);
  mcp4.pinMode(lp, OUTPUT);
  }

Thanks! :slight_smile:

for(byte lp=0;lp<8;p++)
   {
   mcp1.pinMode(lp, INPUT);
   mcp2.pinMode(lp, OUTPUT);
   mcp3.pinMode(lp, OUTPUT);
   mcp4.pinMode(lp, OUTPUT);
   }

saves 2%

wildbill:
Similarly, repeated lines like this:

    drawCentreString("DAC", 27, 15);

Can pull the string they're printing from an array and be done then with a single line of code.

But how to make array from this:

if (Analog == 1)
  {
    drawCentreString("DAC", 27, 15);
  }
  else if (Analog == 2)
  {
    drawCentreString("IN-2", 27, 15);
  }

some ideas how to write this better?

if (vol_temp_2 < volume_old)
    {
      if (relay7 == 0)
      {
        mcp4.digitalWrite(0, LOW);
      }
      else mcp4.digitalWrite(0, HIGH);

      delay(relay_delay);

      if (relay6 == 0)
      {
        mcp4.digitalWrite(1, LOW);
      }
      else mcp4.digitalWrite(1, HIGH);

      delay(relay_delay);

      if (relay5 == 0)
      {
        mcp4.digitalWrite(2, LOW);
      }
      else mcp4.digitalWrite(2, HIGH);

      delay(relay_delay);

      if (relay4 == 0)
      {
        mcp4.digitalWrite(3, LOW);
      }
      else mcp4.digitalWrite(3, HIGH);

      delay(relay_delay);

      if (relay3 == 0)
      {
        mcp4.digitalWrite(4, LOW);
      }
      else mcp4.digitalWrite(4, HIGH);

      delay(relay_delay);

      if (relay2 == 0)
      {
        mcp4.digitalWrite(5, LOW);
      }
      else mcp4.digitalWrite(5, HIGH);

      delay(relay_delay);

      if (relay1 == 0)
      {
        mcp4.digitalWrite(6, LOW);
      }
      else mcp4.digitalWrite(6, HIGH);

      delay(relay_delay);

      if (relay0 == 0)
      {
        mcp4.digitalWrite(7, LOW);
      }
      else mcp4.digitalWrite(7, HIGH);
      volume_old = vol_temp_2;
    }

how to make array from this:

An array of pointers to strings indexed by the value of Analog would do the job

All of this stuff is rearranging the deckchairs. Most of the flash is used by support functions. Libraries, obviously, but other functions like floating-point divide or big-S Strings make a big difference.

If you only used float (anything with a decimal point) in one or two places, try to re-write without it. Look for Strings: they sneak in with example code or old debug prints you forgot about. Once you remove the last String operation, your flash usage will shrink dramatically.

On the other hand, 94% is not bad. You have all the support functions loaded so using float in 100 places in your code doesn't make it grow 10% with every usage.

I need to have float in one place - volume, Im changed value of volume for 0.5

//RGB//
byte redPin = 6;
byte greenPin = 9;
byte bluePin = 12;
//RGB//
byte potPin_red = A1;
byte potPin_green = A2;
byte potPin_blue = A3;
//RGB//
byte readValue_red;
byte readValue_green;
byte readValue_blue;
//RGB//
byte writeValue_red;
byte writeValue_green;
byte writeValue_blue;

//blokady
byte blokadaAnalog = 0;
byte blokadaDigital = 0;
byte blokadaVolume = 0;
byte blokadaRTC = 0;
byte blokadaClearAll = 0;
byte blokadaClearFillAnalog = 0;
byte blokadaClearFillDigital = 0;

//OLED
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define reset 8
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//RTC
#include <DS3231.h>
DS3231 clock;
RTCDateTime dt;

//I2C
#include <Wire.h>
#include "Adafruit_MCP23008.h"
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp1;
Adafruit_MCP23008 mcp2;
Adafruit_MCP23008 mcp3;
Adafruit_MCP23008 mcp4;

//IR
#include <IRremote.h>
#define irPin 5
IRrecv irrecv(irPin);
decode_results results;
byte old_toggle;

//ilosc menu
byte mode = 3;

//ENKODER //A;B;SWITCH
#define rotaryVolL 13
#define rotaryVolR SCK
#define menuVol A0

#define rotarySelL 7
#define rotarySelR SS
#define menuSel A5


bool vol_change;
volatile float vol;

byte Analog_change;
byte Analog;

byte Digital_change;
byte Digital;

boolean rVolL;
boolean rVolR;

boolean rSelL;
boolean rSelR;

byte lock_keyA = 0;
byte lock_keyB = 0;

//menu
byte count = 0;
byte buttonStateA = 0;
byte buttonStateB = 0;

//mute
byte mute_pressed = 0;
float mute_last_value = 0;
boolean lock_mute = 0;
boolean lock_off_mute = 0;

//PVC
float volume = 30;
float volume_old = 1000;
byte energ_relays;
byte energ_relays_old;
byte relay_delay;

#define Vmcp0 64
#define Vmcp1 32
#define Vmcp2 16
#define Vmcp3 8
#define Vmcp4 4
#define Vmcp5 2
#define Vmcp6 1
#define Vmcp7 0.5

boolean relay0 = 0;
boolean relay1 = 0;
boolean relay2 = 0;
boolean relay3 = 0;
boolean relay4 = 0;
boolean relay5 = 0;
boolean relay6 = 0;
boolean relay7 = 0;

but its only 0.5 ... 127 .

If the smallest unit of volume you need to measure is 0.5 then you could count in halves. Divide the internal number by 2 for display. If it is or is not not a whole number result print the string ".0" or ".5" after.

Many bathroom scales work like this. They don't actually measure 0.5kg. They just turn on or off the "5" based on an internal number you can't see.

Good to know.

But anyway. After changed all float to byte still I have about 90%

Good. That seems about right. The float routines are not excessively large but 4% is a significant saving for you when you're looking at the last few percent of capacity.

Even if you didn't use any float type variables, it's not easy to totally eliminate the use of float. You may accidentally multiply by 0.5 in one place and then the whole multiply routine must be compiled. Of course the compiler is extremely good at finding these kids of optimizations for itself. It may have already noticed that it could replace that with an integer divide-by-2, which further optimizes to a bit-shift. But change your constant to 0.4 and it undoes all that.