OLED display suddenly working only with Serial.begin

Suddenly, as in title, I have experienced a strange issue that I cannot solve or comprehend.
Therefore I need your kind help to know where is my mistake.

In the following program I am trying to compare two resistors, one is known, the other is measured (The application is to detect the fuel quantity in a tank and print the value on a small display).
To smooth the signal I have implemented the code found in the tutorial https://www.arduino.cc/en/tutorial/smoothing but putting it in a subfunction for calling once in void setup() an then recursively in the void loop().

Problem is that the code runs fine only with Serial.begin(9600).
If I am removing that, the OLED turns black.
seems like it is stuck inside the function, before issuing u8g2.sendBuffer();

I have also tried to remove the subfuction and put all the code under the loop() and it is working fine! :o
In this way I am sacrificing the fist calculation in the setup() so I would like to fix the issue.

#include <U8g2lib.h>
#include <U8x8lib.h>
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// VCC in pin +5v, GND in GND, SCL in A5, SDA in A4

  //------------------------------------------------------------------------
  //                    VARIABILI
  //------------------------------------------------------------------------

const float Rrefer = 1500;
const int Lmax = 70;
const float radius = 0.3745; // raggio ruota in m; 
const float pi = 3.1416;
const int numReadings = 20;

float v1, Rtest;
// R riferimento tra pin A0 e GND dell'arduino
float STAMPA_L;
float STAMPA_L_init;
float van_speed;
float kml;

unsigned int percentage;
char mybuffer[5];
volatile byte full_revolutions, distance_tick;
unsigned int rpm;
unsigned long timeold, timeold2;

// smoothing vars
float readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
float total = 0;                  // the running total



void setup(void) {
Serial.begin(9600);
  
  u8g2.begin();
  attachInterrupt(0, magnet_detect, RISING);//Initialize the intterrupt pin (Arduino digital pin 2)
  full_revolutions = 0;
  distance_tick = 0;
  rpm = 0;
  timeold = 0;
  timeold2 = 0;
  // initialize all the average reading vars to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }

  calc_liters();

  STAMPA_L_init = STAMPA_L;

}



void loop(void) {
  u8g2.clearBuffer();                    // clear the internal memory

  calc_liters();

  u8g2.setFont(u8g2_font_7x13_tf);  // choose a suitable font
  dtostrf(Rtest, 2, 0, mybuffer);
  u8g2.drawStr(5, 30, mybuffer);
  u8g2.drawStr(30, 30, "ohm");
  // gauge
  dtostrf(STAMPA_L, 2, 0, mybuffer);
  percentage = STAMPA_L / Lmax * 100;
  u8g2.setFont(u8g2_font_7x13_tf);  // choose a suitable font
  u8g2.drawStr(0, 48, "Fuel:"); // write something to the internal memory
  u8g2.drawStr(40, 48, mybuffer); // write something to the internal memory
  u8g2.drawStr(58, 48, "L, ("); // write something to the internal memory
  dtostrf(percentage, 2, 0, mybuffer);
  u8g2.drawStr(88, 48, mybuffer);
  u8g2.drawStr(110, 48, "%)");

  u8g2.drawRFrame(0, 55, 128, 8, 0);
  u8g2.drawBox(0, 55, (percentage * 1.28), 8);

  //------------------------------------------------------------------------
  //                    SPEED and MILEAGE
  //------------------------------------------------------------------------

  if (full_revolutions >= 2) {
    rpm = (60000 / (millis() - timeold) * full_revolutions);
    timeold = millis();
    full_revolutions = 0;
  }

  u8g2.setFont(u8g2_font_7x13_tf); // choose a suitable font
  dtostrf(distance_tick, 3, 0, mybuffer);
  u8g2.drawStr(60, 30, mybuffer);
  u8g2.drawStr(90, 30, "ticks");

  //Speed = 2*pi*r × RPM × (60/1000) km/hr
  van_speed = 2 * pi * radius * rpm * 60 / 1000;
  u8g2.setFont(u8g2_font_t0_22b_tf);  // choose a suitable font
  dtostrf(van_speed, 3, 0, mybuffer);
  u8g2.drawStr(0, 14, mybuffer);
  u8g2.setFont(u8g2_font_t0_12_tf);  // choose a suitable font
  u8g2.drawStr(35, 14, "km/h");

  if ((millis() - timeold2) >= 60000 && distance_tick < 256) {  // every 1 minute is 60000
    timeold2 = millis();
    //kml = (2 * pi * radius * distance_tick / 1000) / (STAMPA_L_init - STAMPA_L);
    kml = (STAMPA_L_init - STAMPA_L);
    STAMPA_L_init = STAMPA_L;
    distance_tick = 0;
  }

  u8g2.setFont(u8g2_font_t0_16b_tf); // choose a suitable font
  dtostrf(kml, 3, 1, mybuffer);
  u8g2.drawStr(70, 14, mybuffer);
  u8g2.setFont(u8g2_font_t0_12_tf);  // choose a suitable font
  u8g2.drawStr(105, 14, "km/l");

  u8g2.sendBuffer();                    // transfer internal memory to the display
  delay(200);
}


void magnet_detect() //This function is called whenever a magnet/interrupt is detected by the arduino
{
  full_revolutions++;
  distance_tick++;
}


void calc_liters()
{
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(A0);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;
  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }
  // calculate the average:
  v1 = total / numReadings;
  v1 = v1 * (5.0 / 1023.0);
  Rtest = (5 - v1) * Rrefer / v1;
  // build equation
  STAMPA_L = (-9.9635e-06 * pow(Rtest, 3)) + (0.0059454 * pow(Rtest, 2)) + (-1.2739 * Rtest) + 104.9;
  // il range è circa 260ohm (0%) - 32 ohm (100%)
}

it must somehow be a memory issue, the Serial.begin() declares the rx-buffer 64 bytes, resolving your issue i suspect nothing to do with Serial specifically. to confirm you could as your final global variable declaration writechar buf[64];and see if that works. This is not the solution of course we need to investigate !
if you would declare inline void calc_liters()the issue should also dissolve, again this is not the solution but just a confirmation of what is happening.
I don't see you writing beyond the size of the array anywhere, but what you describe may be the return address being pushed on the stack, somehow not in 'free' space.

thank you.
I have tried what you have suggested but without any change in the behavior of the system.
still black screen.

to proceed with the debugging I have tried to remove lines one by one and I have identified that the mathematical formula

STAMPA_L = (-9.9635e-06 * pow(Rtest, 3)) + (0.0059454 * pow(Rtest, 2)) + (-1.2739 * Rtest) + 104.9;

is responsible to the issue

indeed if I substitute it with a constant value i.e.

STAMPA_L = 33;

the program will show up in the display.

could it be that it is too complex? :o Is there a way to make it more compatible with the little memory and capabilities of the UNO?

It is still strange to me that including Serial.begin is sufficient for making everything working... even if the refresh rate seems a bit slower.

could it be that it is too complex?

not really, but what if you spread it out over a few lines and not use the pow() function ?

STAMPA_L = 104.9;
STAMPA_L = STAMPA_L - 1.2739 * Rtest;
STAMPA_L = STAMPA_L + 0.0059454 * Rtest * Rtest; 
STAMPA_L = STAMPA_L - 9.9635e-06 * Rtest * Rtest * Rtest;

All are floating point calculations and as such they should be just executed one at a time, so making it look like this doesn't actually matter, but not calling pow() might.

It is still strange to me that including Serial.begin is sufficient for making everything working.

That is mad, and probably completely coincidental .

:frowning:
It withstands only the first three lines to work... I had to comment the last one

STAMPA_L = 104.9;
STAMPA_L = STAMPA_L - 1.2739 * Rtest;
STAMPA_L = STAMPA_L + 0.0059454 * Rtest * Rtest;
//STAMPA_L = STAMPA_L - 9.9635e-06 * Rtest * Rtest * Rtest;

it also works with Rtest^2 in the last line ... but not with three multiplications :confused:

STAMPA_L = 104.9;
STAMPA_L = STAMPA_L - 1.2739 * Rtest;
STAMPA_L = STAMPA_L + 0.0059454 * Rtest * Rtest;
STAMPA_L = STAMPA_L - 9.9635e-06 * Rtest * Rtest;

Even with a simple

STAMPA_L =  Rtest * Rtest * Rtest;

it does not work. :o

is working with:

 Rtest = 200;
STAMPA_L =  Rtest * Rtest * Rtest;

but again not with:

 v1 = 200;
  Rtest = (5 - v1) * Rrefer / v1;
STAMPA_L =  Rtest * Rtest * Rtest;

the code says that I am using 1695 byte (82%) di dinamic memory and that there could be stability issues... I think it is right.. :cold_sweat:

moreover, declaring the two variables types:

int v1; 
int Rtest;

instead of float, makes it work but with strange numbers (of course)

and with:

int v1; 
float Rtest;

a strange behavior occurs, the screen is flashing repetively, on an off..

the code says that I am using 1695 byte (82%)dynamic memory and that there could be stability issues... I think it is right.. :cold_sweat:

Well it must be the OLED library sucking up all your memory, maybe the font you chose. and if it leaves only about 300 bytes of RAM for local variables that may be just not quite enough, still you must have just found the edge somehow ! Probably the best approach is to see what you can minimize in terms of memory usage. is v1 used anywhere outside of void calc_liters() ?
hey actually having 2 fonts, might be just a bit much although they may be stored in progmen but i am not sure

You might try using Bill Greiman's text only library:

I know when I first looked for LCD libraries I found this to be the simplest. I found the "ZevvPeep8x16" font to be the most readable on my 4 line display.

John

u8g2 library is good, but I’ve experienced it using memory, if short I use the adafruit library, it is smaller albeit not as flexible.

#include <U8g2lib.h>
#include <U8x8lib.h>

why call both? you are only using u8g2.