Low memory available, stability problems may occur

I am doing a project which needs to read a modbus slave device, write some values on a OLED 0.96’ display and some actions with outputs.
When I compile the program it shows Low memory available, stability problems may occur.

After running for about 10 minutes the program hangs.( Doesnt respond to inputs)
I tried commenting the OLED update part of the program and solving the low memory issue.

But I need to run the OLED too. My program is attached below.

Is there a better way to run the OLED without consuming much memory.

I am using a Arduino Genuinio/micro built for industrial environments. It programs as a normal arduino board.

display_V3_machine2.ino (9.34 KB)

You have some "fat" in the sketch which could be trimmed away:

  1. define a pin number as a byte, not an int.
  2. Use the F macro to keep strings in the flash memory to minimise RAM usage. Eg:
if(dir==1)display.print(F(" sens"));   // F macro

although for small strings, it may not bring much.

but your big problem is the size of those two Adafruit libraries.

Maybe have a look here: https://www.google.ch/search?source=hp&q=small+ssd1306+library&oq=small+ssd1306

Thanks for suggestions. Trying a small library for the OLED seems to solve the issue.

6v6gt: You have some "fat" in the sketch which could be trimmed away:

  1. define a pin number as a byte, not an int.
  2. Use the F macro to keep strings in the flash memory to minimise RAM usage. Eg:
if(dir==1)display.print(F(" sens"));   // F macro

although for small strings, it may not bring much.

but your big problem is the size of those two Adafruit libraries.

Maybe have a look here: https://www.google.ch/search?source=hp&q=small+ssd1306+library&oq=small+ssd1306

I tried greiman/SSD1306Ascii with my controller. But display doesn’t show any text.

It seems the library is not compatible with the display. The OLED is SSD1306 0.96 Display driven by I2C.

Datasheet of the controller attached.

NORV-Cema-Datasheet.pdf (754 KB)

unsigned long int up_reading = 0;
unsigned long int down_reading = 0;
unsigned int dir = 0;
...
attachInterrupt(digitalPinToInterrupt(7), blink, FALLING);
...
void blink()
{
  if (dir == 1) up_reading += 5;
  else if (dir == 0) down_reading += 5;
}

Variables that you share between normal program flow and an ISR need to be declared as volatile. You would also need to disable interrupts before reading their value in normal program flow to ensure that you are reading them atomically. dir could be a byte.

void auto_mode_on() {
  while (auto_mode == 1) {
...
    while (stage == 0) {
...
    }

    while (stage == 1) {
...
  }
}

Add some diagnostics to these while loops to ensure that you notice if you are getting stuck in them.

Overall, not the most maintainable code that I've ever seen.

I use

include "SSD1306Ascii.h"

include "SSD1306AsciiAvrI2c.h"

with SSD1306 0.96 I2C. I believe they both came from Lady Ada.