Using a 128x64 OLED on a NANO: Strange effect when using different Text size

Hi everybody
On my project with a NANO processor I am using an I2C oled display 128x64 with the Adafruit_SH110X library. It is a kind of Calendar and Clock and my code is pretty simple but long. I am doing some setup procedures like setting the clock and other stuff before I come to the loop which just shows the time on the display.

// New Ring Calendar
// August 2023
// Bernardo Gullasch
// V3.0 10.08.23 New version with OLED display   

#include <Wire.h>
#include <DS3231.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Adafruit_SH1106G oled = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

DS3231 Clock;

int MotDay = 5;
int MotMon = 6;
int MotDoW = 7;
int MotDbl = 4;

int SelBtn = 8;
int SetBtn = 9;

int MotSpd = 500;

bool Century = false;
bool h12;
bool PM;

int DoW;
const char *WeekDay[] = {"Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado", "Domingo"};
bool END;

int Hour;
int Minute;
int Second;
int Block[7];
int i=0;
int y=0;

int SpD = 576; // 6912 Hour Steps per cycle -- 36/12 gear
int SpM = 384; // 23040 Minute Steps per cycle -- 120/12 gear 
int SpW = 576; // 34560 Second Steps per cycle -- 180/12 gear
int DSteps;
int MSteps;
int WSteps;


void setup() 
{
  pinMode(SelBtn, INPUT);
  pinMode(SetBtn, INPUT);

  pinMode(MotDay, OUTPUT);
  pinMode(MotMon, OUTPUT);
  pinMode(MotDoW, OUTPUT);
  pinMode(MotDbl, OUTPUT);

  
  Wire.begin();
  Serial.begin(9600);
  Clock.setClockMode(false);
  oled.begin(0x3C, true); // Address 0x3C default
  oled.display();
  delay(1000);
  oled.clearDisplay();
  oled.setTextSize(1);
  oled.setTextColor(SH110X_WHITE);
  oled.setCursor(10, 10);
  oled.println("RTC actual time is ");
  oled.println("---------------------");
   
    Block[0] = Clock.getYear(), DEC;
    Block[1] = Clock.getMonth(Century), DEC;
    Block[2] = Clock.getDate(), DEC;
    Block[3] = Clock.getDoW(), DEC;
    Block[4] = Clock.getHour(h12,PM), DEC;
    Block[5] = Clock.getMinute(),DEC;
    Block[6] = Clock.getSecond(),DEC;

   oled.setCursor(20,30);
   oled.print(Block[0]);
   oled.print("-");
   oled.print(Block[1]);
   oled.print("-");
   oled.print(Block[2]);
   oled.print(" ");
   oled.print(Block[4]);
   oled.print(":");
   oled.print(Block[5]);
   oled.print(":");
   oled.println(Block[6]);
   oled.display();
   
  while (!digitalRead(SetBtn) && !digitalRead(SelBtn)) {;}
  if (digitalRead(SetBtn)) {delay(200); InputData();}
  delay(1000); 
  
  oled.clearDisplay();
  oled.setTextSize(1);
  oled.setCursor(0,30); oled.print("SetBtn to move Day");
  oled.setCursor(0,40); oled.print("SelBtn to stop");
  oled.display();
  while(!digitalRead(SetBtn)) {;}
  syncDay();
  delay(100);
  
  oled.clearDisplay();
  oled.setCursor(0,30); oled.print("SetBtn to move Mon");
  oled.setCursor(0,40); oled.print("SelBtn to stop");
  oled.display();
  while(!digitalRead(SetBtn)) {;}  
  syncMon();
  delay(100);
   
  oled.clearDisplay();
  oled.setCursor(0,30); oled.print("SetBtn to move Week");
  oled.setCursor(0,40); oled.print("SelBtn to stop");
  oled.display();
  while(!digitalRead(SetBtn)) {;}
  syncDoW(); 
  delay(1000);
  oled.clearDisplay();
  oled.setTextSize(2);
  oled.setCursor(5,30);
  oled.print("* READY *"); 
  oled.display();
  delay(1000);
} //end SETUP

void loop()
{
   oled.clearDisplay();
   oled.setTextSize(1);
   oled.setCursor(0,10);
   i++;
   oled.print("LOOP "); oled.print(i);
   oled.display();
   delay(500);
   //showTime();
   //delay(500);
}

void InputData()
  {
       while (i<7) // input date/time values
        {
        if (digitalRead(SelBtn)) // ajust actual value
         {
          Block[i]++ ;
          if (Block[0] > 32) {Block[0] = 22;}
          if (Block[1] > 12) {Block[1] = 1;}
          if (Block[2] > 31) {Block[2] = 1;}
          if (Block[3] > 7 ) {Block[3] = 1;}
          if (Block[4] > 23) {Block[4] = 0;}
          if (Block[5] > 59) {Block[5] = 0;}
          if (Block[6] > 59) {Block[6] = 0;}      
          
          delay(200);      
         }
         
         showInput();
         
         if (digitalRead(SetBtn)) // set value and goto next 
         {
          i++;
          delay(500);
         }      
        } // ready input date/time values 0 to 5
     
    delay(100);
    while(!digitalRead(SetBtn)) 
    {
    oled.clearDisplay();
    oled.setTextSize(1);
    oled.setTextColor(SH110X_WHITE);
    oled.setCursor(0,12);
    oled.print("Ready for adjust time");
    oled.display();
    }
    SetClock();
  }

void showInput()
 {
  oled.clearDisplay();
  oled.setTextSize(1);
  oled.setTextColor(SH110X_WHITE);
  oled.setCursor(0, 0);
  oled.print("Now input Date/time");
  oled.setCursor(0,8);
  oled.print("---------------------");
  oled.setCursor(0,15);
  oled.print("Year Month Day DoW");
  for (y=0; y<4; y++)
  {
    oled.setCursor((y*30+10),25);
    if (y==i) {oled.setTextColor(SH110X_BLACK, SH110X_WHITE);} else {oled.setTextColor(SH110X_WHITE);}
    oled.print(Block[y]);
  }
  oled.setTextColor(SH110X_WHITE);
  oled.setCursor(0,35);
  oled.print("Hour Minute Second");
  for (y=4; y<7; y++)
  {
   oled.setCursor(((y-4)*30+10),45);
   if (y==i) {oled.setTextColor(SH110X_BLACK, SH110X_WHITE);} else {oled.setTextColor(SH110X_WHITE);}
   oled.print(Block[y]); 
  }
  oled.display();
 } 

 void SetClock()
  {
   Clock.setClockMode(false);
   Clock.setSecond(Block[6]);
   Clock.setMinute(Block[5]);
   Clock.setHour(Block[4]);
   Clock.setDoW(Block[3]);
   Clock.setDate(Block[2]);
   Clock.setMonth(Block[1]);
   Clock.setYear(Block[0]);

   oled.setTextSize(2);
   oled.setTextColor(SH110X_WHITE);
   oled.setCursor(10, 40);
   oled.println("* READY *");
   oled.display();
   delay(1000);   
  }

  void showTime()
  {
   Hour = Clock.getHour(h12, PM), DEC;
   Minute = Clock.getMinute(), DEC;
   Second = Clock.getSecond(), DEC;
   
   oled.clearDisplay();
   oled.setTextSize(1);
   oled.setTextColor(SH110X_WHITE);
   oled.drawRect(25,35,65,20,SH110X_WHITE);
   oled.setCursor(35,40);
   if(Hour < 10) {oled.print("0");}
   oled.print(Hour);
   oled.print(":");
   if(Minute < 10) {oled.print("0");}
   oled.print(Minute);
   oled.print(":");
   if(Second < 10) {oled.print("0");}
   oled.print(Second); 
   oled.display();
   delay(100);
  }

  void runDay() //Day Ring
{
  // MAKE DAY RING MOVE
  digitalWrite(MotDbl, LOW);
  for (int i = DSteps; i > 0; i--)
   { 
     digitalWrite(MotDay, HIGH);
     delayMicroseconds(MotSpd);
     digitalWrite(MotDay, LOW);
     delayMicroseconds(MotSpd);
   }
  digitalWrite(MotDbl, HIGH);

Serial.println("-------------------------");
  
   DSteps = 0;  
}

void runMon() //Month Ring
{
  
  // MAKE MONTH RING MOVE
  digitalWrite(MotDbl, LOW);
  for (int j = MSteps; j > 0; j--)
   { 
     digitalWrite(MotMon, HIGH);
     delayMicroseconds(MotSpd);
     digitalWrite(MotMon, LOW);
     delayMicroseconds(MotSpd);
   }
  digitalWrite(MotDbl, HIGH);

Serial.println("-------------------------");   
   MSteps = 0;  
}

void runDoW() // Day of week Ring
{  
  // MAKE DOW RING MOVE
  digitalWrite(MotDbl, LOW);
  for (int k = WSteps; k > 0; k--)
   { 
     digitalWrite(MotDoW, HIGH);
     delayMicroseconds(MotSpd);
     digitalWrite(MotDoW, LOW);
     delayMicroseconds(MotSpd);
   }
  digitalWrite(MotDbl, HIGH);

Serial.println("-------------------------");   
   WSteps = 0;  
}

void syncDay() // Day of week Ring
{  
  // MAKE DAY RING MOVE
  digitalWrite(MotDbl, LOW);
  while(!digitalRead(SelBtn))
   { 
     digitalWrite(MotDay, HIGH);
     delayMicroseconds(MotSpd);
     digitalWrite(MotDay, LOW);
     delayMicroseconds(MotSpd);
   }
  digitalWrite(MotDbl, HIGH); 
}

void syncMon() // Day of week Ring
{  
  // MAKE MONTH RING MOVE
  digitalWrite(MotDbl, LOW);
  delay(100);
  while(!digitalRead(SelBtn))
   { 
     digitalWrite(MotMon, HIGH);
     delayMicroseconds(MotSpd);
     digitalWrite(MotMon, LOW);
     delayMicroseconds(MotSpd);
   }
  digitalWrite(MotDbl, HIGH); 
}

void syncDoW() // Day of week Ring
{  
  // MAKE DOW RING MOVE
  digitalWrite(MotDbl, LOW);
  while(!digitalRead(SelBtn))
   { 
     digitalWrite(MotDoW, HIGH);
     delayMicroseconds(MotSpd);
     digitalWrite(MotDoW, LOW);
     delayMicroseconds(MotSpd);
   }
  digitalWrite(MotDbl, HIGH); 
}

Now what happens is very strange. The code just like it shows here with a textsize (1) and showTime() funktion disabled (commented) works fine. As soon as I change the textsize to (2) or bigger. the display in setup funktion messed up and when it comes to the loop funktion it crashes (resets the processor). It seems directly related to the textsize, if it is 1 it works if it is 2 it crashes. Even stranger is that I am using textsize 2 just to display "READY right before the loop starts and this is working ok.
can anybody explain this effect ? What am I doing wrong ?

There are eight occurrences of "setTextSize(x)"... Changing the first one seems to make "strange things happen." Changing "setTextSize(x)" in occurrence two through eight does not make strange things happen.... HOWEVER; no text size on the OLED is changed. Perhaps setting "2" at that point makes the screen buffer overflow? Maybe the library only wants "1"? Interesting...

If you change oled.setCursor(10, 10); to oled.setCursor(0, 0);, you will see in (1, 0) that something is madly writing a character... perhaps that is also a problem...

this makes sense, but continuing on my research I found that it works with size 2 if I change printing plain text between "" instead of a variable like the hour from the clock

definitly if I put oled.print("plain Text"); it works
if I put oled.print(Hour); it crashes

is there any alternative library for my I2C OLED display ?
the SSD1306 libraries don´t work at all

i tried this one:

void loop()
{
   Hour = Clock.getHour(h12, PM);
   Minute = Clock.getMinute();
   Second = Clock.getSecond();
   i++;
   
   oled.clearDisplay();
   oled.setTextSize(2);
   oled.setCursor(0,0);
   oled.println("Textsize 2");
   //if(Hour < 10) {oled.print("0");}
   //oled.print(Hour);
   //oled.print(":");
   //if(Minute < 10) {oled.print("0");}
   //oled.print(Minute);
   //oled.print(":");
   if(Second < 10) {oled.print(i);}
   oled.print("fix Text");
   oled.display(); 
   //showAnyText();
   //showTime();
   delay(500);
}

as long as the seconds from the clock are higher than 10 I get an output on the display. When the if-case is true.... crash

If you put

  oled.setTextSize(2);
  oled.println("----------");

anywhere before

  oled.println(Block[6]);
  oled.display();

It crashes... so... take a look at "block" things being collected...

Yep... I commented-out all the "oled.block" lines, put in setTextSize(2); and no crash... look at the amount of data collected (and stored in Arduino memory)... and a different way to collect and display it. NOPE...

It is this line:

  // oled.setCursor(20, 30);

Comment it out and use size 2 any time.

Hmm... when I do (the above) things, it works once or five times, then it does not work... still looking when is the right time to use "2"

it highly looks like a memory buffer problem, I think I need another library

You are probably running out of RAM memory. Post the result of compiling, where it shows you how much dynamic memory is left (and subtract 1024 bytes for the display).

You can free up dynamic RAM by putting all the print strings in program memory, using the F macro. For example, replace all lines with .print statements, like this one:

oled.print("SetBtn to move Mon");

with the following change:

oled.print(F("SetBtn to move Mon"));
1 Like

@jremington - This worked here. 27 of the (F(...)). Now, setTextSize(2) works.

YESSSS :slight_smile: it´s magic. Now it works on my side too
thanks a lot guys, I´m really happy thank you all experts :wink:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.