Global variables uses almost 90% of my memory. How to reduce it?

Hello guys,

my project is to create a autonomous humidifier using Arduino Uno that has LED screen and a DHT11 sensor which measure humidity surrounding and when it reaches low humidity, the RF transmitter connected to the board would send the binary code to the radio-controlled sockets which the humidifier is connected to to turn it on/off.

The code that I’ve written can be found in the attachment…

The thing is, I’ve tested the programs before partly (such as DHT sensor and RF transmitter / DHT sensor and Display) and they worked perfectly fine separately with the pairs, though i was given a warning of ’ memory available stability problems may occur’ from the DHT and Display pair which states as below; though they are still working:

[

Sketch uses 15360 bytes (47%) of program storage space. Maximum is 32256 bytes.
Global variables use 1590 bytes (77%) of dynamic memory, leaving 458 bytes for local variables. Maximum is 2048 bytes.

As soon as I compiled everything together (DHT, RF transmitter, and Display), it shows as below.

Sketch uses 18250 bytes (56%) of program storage space. Maximum is 32256 bytes.
Global variables use 1788 bytes (87%) of dynamic memory, leaving 260 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.

The display didnt even show anything, same as the serial monitor as it doesnt show any value. I tried to reduce anything such as including PROGMEM and F(macro) in my sketch, but that doesnt seem to do enough. Is there anyway how I can make this sketch works? Your insight and idea would be much appreciated.

display2.ino (4.55 KB)

Please post the code rather than attaching it. Some devices do not show the .ino files.

For those interested:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>
#include "DHT.h" //loading DHT library
#include <RCSwitch.h> //loading RC Switch

#define DHTPIN 2 //Connect module to Pin 2    
#define DHTTYPE DHT11  
#define OLED_RESET 4

RCSwitch mySwitch = RCSwitch();
DHT dht(DHTPIN, DHTTYPE);
Adafruit_SH1106 display(OLED_RESET);


//Cloud Image//
constexpr PROGMEM const uint8_t Cloud[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,255,192,0,0,0,0,0,0,0,0,0,63,255,240,0,0,0,0,0,0,0,0,0,255,255,252,0,0,0,0,0,0,0,0,3,255,255,255,0,0,0,0,0,0,0,0,7,255,255,255,128,0,0,0,0,0,0,0,15,255,255,255,224,0,0,0,0,0,0,0,31,255,255,255,240,0,0,0,0,0,14,0,63,255,255,255,240,0,0,0,0,1,255,224,127,255,255,255,248,0,0,0,0,7,255,248,255,255,255,255,252,0,0,0,0,15,255,252,255,255,255,255,254,0,0,0,0,63,255,255,255,255,255,255,254,0,0,0,0,127,255,255,255,255,255,255,255,0,0,0,0,127,255,255,255,255,255,255,255,0,0,0,0,255,255,255,255,255,255,255,255,128,0,0,1,255,255,255,255,255,255,255,255,128,0,0,1,255,255,255,255,255,255,255,255,128,0,0,3,255,255,255,255,255,255,255,255,128,0,0,3,255,255,255,255,255,255,255,255,192,0,0,3,255,255,255,255,255,255,255,255,192,0,0,3,255,255,255,255,255,255,255,255,192,0,0,7,255,255,255,255,255,255,255,255,192,0,0,7,255,255,255,255,255,255,255,255,192,0,0,7,255,255,255,255,255,255,255,255,192,0,0,15,255,255,255,255,255,255,255,255,240,0,0,63,255,255,255,255,255,255,255,255,252,0,0,255,255,255,255,255,255,255,255,255,255,0,1,255,255,255,255,255,255,255,255,255,255,128,3,255,255,255,255,255,255,255,255,255,255,192,7,255,255,255,255,255,255,255,255,255,255,224,15,255,255,255,255,255,255,255,255,255,255,240,31,255,255,255,255,255,255,255,255,255,255,248,31,255,255,255,255,255,255,255,255,255,255,248,63,255,255,255,255,255,255,255,255,255,255,252,63,255,255,255,255,255,255,255,255,255,255,252,127,255,255,255,255,255,255,255,255,255,255,254,127,255,255,255,255,255,255,255,255,255,255,254,127,255,255,255,255,255,255,255,255,255,255,254,127,255,255,255,255,255,255,255,255,255,255,254,82,81,36,146,146,73,36,73,36,146,73,38,64,0,0,0,0,0,0,0,0,0,0,2,64,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
//Droplet Image//
constexpr PROGMEM const uint8_t Drop[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,128,0,0,1,128,0,0,1,128,0,0,3,192,0,0,3,192,0,0,7,224,0,0,7,224,0,0,15,240,0,0,15,240,0,0,31,248,0,0,31,248,0,0,31,248,0,0,31,248,0,0,31,248,0,0,31,248,0,0,15,240,0,0,15,240,0,0,7,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
//const unsigned char PROGMEM


void setup()   {                
  Serial.begin(9600);

  //Sensor begin
  dht.begin(); 
  
  //Initialize the Display
  display.begin(SH1106_SWITCHCAPVCC, 0x3C);  
  display.clearDisplay();
  display.display();
 // display.setTextSize(0);
 // display.setFont();
 // display.setTextColor(WHITE);
 //

//Main Program for Switching
  mySwitch.enableTransmit(10); // Transmitter is connected to Arduino Pin #10  
  mySwitch.setProtocol(4); // Optional set protocol (default is 1, will work for most outlets)
  mySwitch.setPulseLength(348);  // Optional set pulse length.

}


void loop() {

//Sensor function and Data at Serial Monitor
delay(2000);
float rh = dht.readHumidity();
float temp = dht.readTemperature();
 Serial.print(F("Humidity: "));
  Serial.println(rh);
  Serial.print(F("Temperature: "));
  Serial.print(temp);
  Serial.println(F("°C "));
  
//Display function for Sensor Data
 
  display.setCursor(5, 5);
  display.setTextSize(4);
  display.println(temp, 0);
  display.setCursor(50, 5);
  display.setTextSize(1);
  display.println(F("C"));
  display.setCursor(85, 5);
  display.setTextSize(2);
  display.print(rh, 0); 
  display.println(F("%"));  
  //display.drawBitmap(0,30,Cloud,96,64, 1);
  display.drawBitmap(60,0,Drop,32,32, 1);
  display.display(); //you have to tell the display to...display
  delay(2000);
  display.clearDisplay();


//RF transmission function
 if(temp < 20){
  mySwitch.send("001001110100101101011100");
 }else if(temp > 24){
  mySwitch.send("001000010110010010001100"); 
  }
  else{}

}

You cannot just change things to PROGMEM and expect them to work. I expect that the library call to drawBitmap() does not expect PROGMEM data but in-RAM data, which explains why it won't show anything and probably would crash the program.

I would start by not including the large arrays and build it up from there to see when it stops working. 'Stability' problems only happen if the stack gets too big (ie, you have a lot of dynamic data). I can't see that in your sketch but don't know what could be happening in the libraries.

Looks like you are trying to run this on an Uno or similar, once solution maybe to try a Mega instead as that has 8k ratherthan 2k of dynamic memory. I have no idea what restrictions you have or whether using a Mega is feasible for you, but it might solve your problem without spending an age reviewing and optimising code.

marco_c: You cannot just change things to PROGMEM and expect them to work. I expect that the library call to drawBitmap() does not expect PROGMEM data but in-RAM data, which explains why it won't show anything and probably would crash the program.

The drawBitmap() function assumes the array is in PROGMEM if the array is declared const, if not declared const it is assumed to be in ram.

You may be able to save some ram by using the u8g2 library with a frame buffer instead of full buffer, or if text only is acceptable the u8x8 library which does not use a buffer.