SSD1306Wire.h and RTClib.h conflict(?)

Hello Community,

I am new at the Arduino World. I am working on a project to display Date/Time provided by the RTC(DS1307) onto an OLED(SSD1306). The controller boards is an ESP8266-12E(NodeMCUv1.0) and these 2 modules are connected via I2C, defaults pins(4,5). The schematic is included below. I have tried different libraries and at the end, I selected (SSD1306.h + Wire.h) or (SSD1306Wire.h) for the OLED, and RTClib.h for the DS1307. Both libraries work fine; one displaying data on the OLED and the other informing the Date/Time via Serial. The problem begins when I try display the Date/Time on the OLED display. The code starts running normally, I can see the Date/Time from RTC (rtc.begin()=1 and rtc.isrunning()=1), but as soon as OLED is initialized (display.init()), the RTC stops (rtc.begin()=0 and rtc.isrunning()=0). From this point there are not Date/Time updates anymore, but the code still running, displaying “165/165/2165 165:165:85” (as Day/Month/Year Hour:Min:Sec via Serial). On the 2nd cycle of the loop(), when the code try to execute the line* after “//Line_2”, system then crashes and about 10 seconds later, the H-WDT resets the controller… If we comment the line* ( display.drawString(C1,L2, String(week[wd])+ " " +String(mes[mo - 1])); ), the controller will not crash anymore, but the RTC will continued dead…

I need help to debug this problem and find a solution (or another library). I´m sure it is possible and usual to have these 2 modules working together on the same I2C once they have different addresses.

I also notice some garbage on the OLED screen when the RTC crashes, specifically on the area where “week[wd]” suppose to be displayed. Looks like the code is invading the part of the memory used as a buffer for SSD1306 (I am guessing). I would appreciate any help on how configure/reserve the memory(ies) to avoid it.

Here is my code…

/*
  MicroController: ESP8266-12E(NodeMCU)
  Modules: SDcard + RTC(DS1307) + OLED(SSD1306) 

  The circuit:
  RTC(DS1307) & OLED(SSD1306) attached to I2C (4,5), as follows:
  
                      ESP12E   
                      ------
 ** SDA --- pin       04(D2)
 ** SCL --- pin       05(D1) 
 ** SSD1306 Addr:     0x3C
 ** DS1307 Addr:      0x68
*/

//Libraries---------------------
#include "RTClib.h"
#include "SSD1306Wire.h"


//Object Declarations-----------
RTC_DS1307 rtc;
SSD1306Wire display(0x3c, 4, 5);  // (I2C_ADDRESS, SDA, SCL) ...Initialize the OLED display using Arduino Wire.h


//< RTC >-----------------------
DateTime now = rtc.now(); // >>> does not work placed here
long lastm;
byte RTC_ok;
bool rok1, rok2;

// date and time variables
byte mm = 0;          // contains the minutes, refreshed each loop
byte hh = 0;          // contains the hours, refreshed each loop
byte ss = 0;          // contains the seconds, refreshed each loop
byte mo = 0;          // contains the month, refreshes each loop
int yr = 0;           // contains the year, refreshed each loop
byte dy = 0;          // contains the day (1-31)
byte wd = 0;          // contains day of week (0-6)
String dataString;



//< SSD1306 >-------------------
#define SCREEN_WIDTH 128          // OLED display width, in pixels
#define SCREEN_HEIGHT 64          // OLED display height, in pixels 
#define line1 0,12,128            // just a line
byte C1=2;                        // Matrix 3x4 1st colunm x-coordinate
byte C2=45;                       // Matrix 3x4 2nd colunm x-coordinate
byte C3=88;                       // Matrix 3x4 3rd colunm x-coordinate
byte L1=15;                       // Matrix 3x4 1st line y-coordinate
byte L2=27;                       // Matrix 3x4 2nd line y-coordinate
byte L3=39;                       // Matrix 3x4 3rd line y-coordinate
byte L4=51;                       // Matrix 3x4 4th line y-coordinate

char *mes[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "zzzzz", "yyyyyy", "xxxxxx"};
char *week[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "zzzzz", "yyyyyy", "xxxxxx"};


void setup()  
{//===============================================================

dataString.reserve(128);


// >>>  SERIAL begin 
  Serial.begin(115200);  // Open serial communications and wait for port to open:
  while (!Serial); {;} // wait for serial port to connect. Needed for native USB
  Serial.println();
  Serial.println();  
  Serial.println("system starting up!");

  
// >>>  WIRE begin
  Wire.begin(4, 5);   // 4=sda, 5=scl


// >>>  RTC begin
  rok1 = rtc.begin();
  rok2 = rtc.isrunning();
  if (!rok1) 
        {
        Serial.println("RTC not found");
        RTC_ok = 0;
        Serial.flush();   //what for?
        abort();          //What does it do???
        }
  else 
        {
        Serial.println("RTC found!");            
        if (!rok2) 
              {
              rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //setting RTC to date&time of sketch compilation                           
              Serial.println("RTC found, but NOT running! (Re)setting now...");              
              }
        if (rok2)  
              {
              RTC_ok = 2;
              Serial.println("RTC found and running OK!");
              DateTime now = rtc.now();
                wd = now.dayOfTheWeek();
                yr = now.year();
                mo = now.month();
                dy = now.day();
                hh = now.hour();
                mm = now.minute();
                ss = now.second();
              dataString = String(dy) + '/' + String(mo) + '/' + String(yr) + "  " + String(hh) + ':' + String(mm) + ':' + String(ss);
              }
        else  
              {
              RTC_ok = 1;
              Serial.println("RTC found, but NOT running! (check the battery CR1220)");                          
              }
        }


//  >>> SSD1306 begin 
  display.init();                     // initialize dispaly
  display.clear();
  display.display();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);  // (sizes available _10, _16, _24)
  display.setContrast(255);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setColor(INVERSE);          // display.setColor(pixelcolor), pixelcolor can be: BLACK, WHITE, INVERSE


  Serial.println(dataString); 
} //End of SETUP 


void loop()   {//===============================================================

  yield();
 
  Serial.print(String(millis()) + " rtc.begin:" + String(rok1) + " rtc.isRunning:" + String(rok2) + " # ");
  Serial.println(dataString);
  
  //... Display (every 1s) .................
  display.clear();
    Serial.print("debug-0"); 
  //Line_0
  display.drawString(0,0,"System Status"); 
  display.drawHorizontalLine(line1);          
    Serial.print("-1"); 
  //Line_1
  display.drawString(C1,L1,"RTC"+String(RTC_ok)+": " + String(dy) + "  " + String(hh) + ":" + String(mm) + ":" + String(ss));  
    Serial.print("-2");   
  //Line_2 
  display.drawString(C1,L2, String(week[wd])+ "  " +String(mes[mo - 1])); //(commenting this line, the program will not be reset by WDT)
    Serial.print("-3");   
  //Line_3
  display.drawString(C1,L3,"Rtc.begin:" + String(rok1) + " .isrunning:" + String(rok2)); 
    Serial.print("-4"); 
  //Line_4
  display.drawString(C1,L4,"RunTime(s):" + String(millis()/1000));
    Serial.print("-5"); 
  display.display();  // Display the buffer
    Serial.print("-6"); 
  delay(1000); 
    Serial.println("-7");
    
  //... RTC (every 10s)......................
  if (millis()-lastm >= 10000)      
      {
        Serial.print("debug=0");  
      lastm = millis();
        Serial.print("=1");  
      rok1 = rtc.begin();
        Serial.print("=2");
      rok2 = rtc.isrunning();
        Serial.print("=3");  
      DateTime now = rtc.now();
        Serial.print("=4");
      wd = now.dayOfTheWeek();
        Serial.print("=5");
      yr = now.year();
        Serial.print("=6");
      mo = now.month();
        Serial.print("=7");
      dy = now.day();
        Serial.print("=8");
      hh = now.hour();
        Serial.print("=9");
      mm = now.minute();
        Serial.print("=A");
      ss = now.second();     
        Serial.print("=B");
      dataString = String(dy) + '/' + String(mo) + '/' + String(yr) + "  " + String(hh) + ':' + String(mm) + ':' + String(ss);
        Serial.println("=C");
      }
         
} //End of LOOP

Reset_Msg.txt (268 Bytes)

You can not access anything on the i2c bus before your Wire.begin() statement. This means you can't have global variables like

DateTime now = rtc.now(); // >>> does not work placed here

Once you have called .begin() in setup(), you should not be calling it again inside loop().

It would also be valuable to share what is displayed on the serial Monitor during execution.

Note: The way i2c works, if a device is not responding such as reading the RTC, you will get every bit read as a '1' which will translate into that crazy date you reference.

Hi Faraday, thanks for your time and thanks for the valuable information as well.

I did the changes you recommend, but still not solving the problem.
I am attaching the code modified, as well as the Exception Decoder message.

Commenting the line 146 (pointed at the report as the problem), the code start running normally (no more resets), however the RTC stops to work anyway… Would you have any other suggestion?

Could you also, please, tell me how to code the line 146 to avoid the resets?

Many thanks in advance,

FM

ESP12E_Code1.ino (6.25 KB)

ExceptionDecoder.txt (1.55 KB)

You are probably getting a bad reading from your RTC which set ‘wd’ or ‘mo’ to a value that doesn’t work as an index into their arrays so you are trying to access memory that is not yours.

Do some sanity checking. Also variables dealing with time ‘lastm’ need to be unsigned long

/*
  MicroController: ESP8266-12E(NodeMCU)
  Modules: SDcard + RTC(DS1307) + OLED(SSD1306)

  The circuit:
  RTC(DS1307) & OLED(SSD1306) attached to I2C (4,5), as follows:

                  ESP12E
                  ------
 ** SDA --- pin   04(D2)
 ** SCL --- pin   05(D1)
 ** SSD1306 Addr: 0x3C
 ** DS1307 Addr:  0x68
*/

//Libraries---------------------
#include "RTClib.h"
#include "SSD1306Wire.h"


//Object Declarations-----------
RTC_DS1307 rtc;
SSD1306Wire display(0x3c, 4, 5);  // (I2C_ADDRESS, SDA, SCL) ...Initialize the OLED display using Arduino Wire.h


//< RTC >-----------------------
unsigned long lastm;
byte RTC_ok;
bool rok1, rok2;

// date and time variables
byte mm = 0;          // contains the minutes, refreshed each loop
byte hh = 0;          // contains the hours, refreshed each loop
byte ss = 0;          // contains the seconds, refreshed each loop
byte mo = 0;          // contains the month, refreshes each loop
int yr = 0;           // contains the year, refreshed each loop
byte dy = 0;          // contains the day (1-31)
byte wd = 0;          // contains day of week (0-6)
String dataString;



//< SSD1306 >-------------------
#define SCREEN_WIDTH 128          // OLED display width, in pixels
#define SCREEN_HEIGHT 64          // OLED display height, in pixels 
#define line1 0,12,128            // just a line
byte C1 = 2;                      // Matrix 3x4 1st colunm x-coordinate
byte C2 = 45;                     // Matrix 3x4 2nd colunm x-coordinate
byte C3 = 88;                     // Matrix 3x4 3rd colunm x-coordinate
byte L1 = 15;                     // Matrix 3x4 1st line y-coordinate
byte L2 = 27;                     // Matrix 3x4 2nd line y-coordinate
byte L3 = 39;                     // Matrix 3x4 3rd line y-coordinate
byte L4 = 51;                     // Matrix 3x4 4th line y-coordinate

char *mes[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
char *week[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};


void setup()  //================================================================
{
  // >>>  WIRE begin
  Wire.begin(4, 5);   // 4=sda, 5=scl

  dataString.reserve(128);

  // >>>  SERIAL begin
  Serial.begin(115200);  // Open serial communications and wait for port to open:
  while (!Serial); {
    ; // wait for serial port to connect. Needed for native USB
  }
  Serial.println();
  Serial.println();
  Serial.println("system starting up!");


  // >>>  RTC begin
  rok1 = rtc.begin();
  rok2 = rtc.isrunning();
  if (!rok1)
  {
    Serial.println("RTC not found");
    RTC_ok = 0;
    Serial.flush();   //what for?
    abort();          //What does it do???
  }
  else
  {
    Serial.println("RTC found!");
    if (!rok2)
    {
      rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //setting RTC to date&time of sketch compilation
      Serial.println("RTC found, but NOT running! (Re)setting now...");
    }
    if (rok2)
    {
      RTC_ok = 2;
      Serial.println("RTC found and running OK!");
    }
    else
    {
      RTC_ok = 1;
      Serial.println("RTC found, but NOT running! (check the battery CR1220)");
    }
  }
  lastm = -20000;
  checkTime();

  //  >>> SSD1306 begin
  display.init();                     // initialize dispaly
  display.clear();
  display.display();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);  // (sizes available _10, _16, _24)
  display.setContrast(255);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setColor(INVERSE);          // display.setColor(pixelcolor), pixelcolor can be: BLACK, WHITE, INVERSE

  Serial.println(dataString);
} //End of SETUP


void loop()   //===========================================================================================
{
  yield();
  Serial.print(String(millis()) + " # ");
  Serial.println(dataString);

  checkTime();
  
  //... Display (every 1s) .................
  display.clear();
  Serial.print("debug-0");
  //Line_0
  display.drawString(0, 0, "System Status");
  display.drawHorizontalLine(line1);
  Serial.print("-1");
  //Line_1
  display.drawString(C1, L1, "RTC" + String(RTC_ok) + ": " + String(dy) + "  " + String(hh) + ":" + String(mm) + ":" + String(ss));
  Serial.print("-2");
  //Line_2
  display.drawString(C1,L2, String(week[wd])+ "  " +String(mes[mo - 1])); //(commenting this line, the program will not be reset by WDT)
  Serial.print("-3");
  //Line_3
  Serial.print("-4");
  //Line_4
  display.drawString(C1, L4, "RunTime(s):" + String(millis() / 1000));
  Serial.print("-5");
  display.display();  // Display the buffer
  Serial.print("-6");
  delay(1000);
  Serial.println("-7");

} //End of LOOP

checkTime()
{
  //... RTC (every 10s)......................
  if (millis() - lastm >= 10000)
  {
    lastm = millis();
    Serial.print("debug=0");
    Serial.print("=1");
    DateTime now = rtc.now();
    Serial.print("=2");
    wd = now.dayOfTheWeek();
    Serial.print("=3");
    yr = now.year();
    Serial.print("=4");
    mo = now.month();
    Serial.print("=5");
    dy = now.day();
    Serial.print("=6");
    hh = now.hour();
    Serial.print("=7");
    mm = now.minute();
    Serial.print("=8");
    ss = now.second();
    Serial.print("=9");
    dataString = String(dy) + '/' + String(mo) + '/' + String(yr) + "  " + String(hh) + ':' + String(mm) + ':' + String(ss);
    Serial.println("=A");

    // make sure weekday and month are in range since
    // they are used as an index into another array
    if ( wd < 0 || wd > 6 )
    {
      Serial.println( "weekday out of range" );
      wd = 0;
    }
    if ( mo < 1 || wd > 12 )
    {
      Serial.println( "month out of range" );
      mo = 1;
    }
}