OLED + DS3231 (RTC) +DHT22 Project

Hello everyone,

I am not very experienced with arduino so I'll do my best to offer all the required information, thank you for your help patience

Goal of project
I want to be able to display temperature, humidity, time, and the state of two binary sensors. The program is meant to control two relays that will activate for different lengths of time given several data combinations.

Reference working program
I managed to make a program that properly displays the information I want, it also works having the display initialization in the void setup (no flashing screen). In this program however, I have no if statements which I suspect might somehow be assisting in some way to the issues I'm facing;

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <I2C_RTC.h>
#include <DHT.h>

static DS3231 RTC;
Adafruit_SH1107 display = Adafruit_SH1107(64, 128, &Wire);

#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

int RedLedPin = 17;
int DV_W = 8;
int MK_W = 7;
int DV_R = 10;
int MK_R = 9;

void setup() {
  Serial.begin(115200);
  RTC.begin();
  RTC.setHourMode(CLOCK_H24);
  dht.begin();
  Wire.begin();

  display.begin(0x3C);
  display.setRotation(3);
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
}

void loop() {
  int DV_N = digitalRead(DV_W);
  int MK_N = digitalRead(MK_W);
  int hrs = RTC.getHours();
  int min = RTC.getMinutes();
  int sec = RTC.getSeconds();
  float temp = dht.readTemperature();
  float hum = dht.readHumidity();

  display.clearDisplay();

  display.setCursor(0, 0); display.print(hrs); display.write(':'); display.print(min); display.write(':'); display.println(sec);
  display.drawLine(0, 9, 48, 9, SH110X_WHITE);
  display.setCursor(0, 18); display.print("T:"); display.setCursor(14, 18); display.print(temp); display.println("C");
  display.setCursor(0, 31); display.print("H: "); display.setCursor(14, 31); display.print(hum); display.setCursor(46, 31); display.println("%"); 
  display.setCursor(0, 46); display.print("MK: "); display.setCursor(18, 46); display.print(MK_N); display.print(" DV: "); display.setCursor(48, 46);  display.print(DV_N);
  display.display();



  delay(5000);
}

Hardware
If it helps, I'm using an arduino nano, a DHT22, a DS3231 (RTC) and a SH1107 I2C 64*128 display I purchased on Aliexpress (model GME64128-02 version 1). The RTC and SH1107 are wired exactly the same, using the SDA and SCL pins on the nano. The DHT 22 uses the pin 2.

Issues so far
Two main issues stand out, when I display more than a given number of characters (total in the code) in the serial monitor, the program just stops working, even if I place a Serial.print at the very beginning of the program, nothing happens (even the Tx light also stops flashing periodically). This is the part I fount the most odd since it occured no matter which Serial.print command I modified in the program.

Secondly, when I run the code only initializing the display with the "display.begin(0x3C, true);" in the void setup, nothing gets displayed on the screen. However, if I place the "display.begin(0x3C, true);", the screen (expectedly) flashes entirely but manages to refresh, normally I wouldn't bother fixing the flashing screen, but after a few iterations of the loop (around 7-11 screen refreshes) and the entire program freezes the same way that it freezes with the first problem.

This is the program I have so far (don't mind that some parts say "do nothing"):

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <I2C_RTC.h>
#include <DHT.h>

static DS3231 RTC;
Adafruit_SH1107 display = Adafruit_SH1107(64, 128, &Wire);

#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

bool RTCstate = false;
bool DHTstate = false;
bool MistTimeState = false;
bool DVstate = false;
bool MKstate = false;
bool Hstate = false;

int DV = 10;
int MK = 9;
int redled = 17;

void setup() {
  Serial.begin(115200);
  RTC.begin();
  RTC.setHourMode(CLOCK_H24);
  dht.begin();
  Wire.begin();

  display.begin(0x3C, true);
  display.setRotation(3);
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
}

void loop() {
  int DV_N = digitalRead(8);
  int MK_N = digitalRead(7);
  int DV = 10;
  int MK = 9;
  int hrs = RTC.getHours();
  int min = RTC.getMinutes();
  int sec = RTC.getSeconds();
  float temp = dht.readTemperature();
  float hum = dht.readHumidity();

  Serial.print(hrs); Serial.print(":"); Serial.print(min); Serial.print(":"); Serial.println(sec);
  Serial.print(F("Temp:")); Serial.println(temp);
  Serial.print(F("Humidity: ")); Serial.println(hum);
  Serial.print("MK:"); Serial.println(MK_N); Serial.print("DV:"); Serial.println(DV_N);
  delay(1000);

  display.begin(0x3C);
  display.setRotation(3);
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE,SH110X_BLACK);
  display.clearDisplay();
  display.setCursor(5, 0);
  display.print(hrs); display.write(':'); display.print(min); display.write(':'); display.println(sec);
  display.drawLine(0, 9, 60, 9, SH110X_WHITE);
  display.setCursor(5, 18); display.print("T:"); display.setCursor(19, 18); display.print(temp); display.println("C");
  display.setCursor(5, 31); display.print("H: "); display.setCursor(19, 31); display.print(hum); display.setCursor(51, 31); display.println("%"); 
  display.setCursor(5, 46); display.print("MK: "); display.setCursor(23, 46); display.print("  "); display.print(" DV: "); display.setCursor(58, 46);  display.print(" ");
  
  if(hrs > 24){ RTCstate = false; Serial.println("RTC:F");}
  if(hrs <= 24){ RTCstate = true; Serial.println("RTC:T");}

  if(isnan(hum)){ DHTstate = false; Serial.println("DHT:F");}
  if(!isnan(hum)){ DHTstate = true; Serial.println("DHT:T");}

  if(hum < 60){ Hstate = false; Serial.println("H:F");}
  if(hum >= 60){ Hstate = true; Serial.println("H:T");}

  if(MK_N == 0){ MKstate = false; Serial.println("MK:F"); display.setCursor(23, 46); display.print("!"); digitalWrite(redled, HIGH);}
  if(MK_N == 1){ MKstate = true; Serial.println("MK:T"); display.setCursor(23, 46); display.print("OK");}

  if(DV_N == 0){ DVstate = false; Serial.println("DV:F"); display.setCursor(58, 46); display.print("!"); digitalWrite(redled, HIGH);}
  if(DV_N == 1){ DVstate = true; Serial.println("DV:T"); display.setCursor(58, 46); display.print("OK");}

  if ((min == 0) && (hrs % 2 == 1) && (sec == 0)) {
    MistTimeState = true;
    Serial.println("MT:T");
  } else {
    MistTimeState = false;
    Serial.println("MT:F");
  }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


  if(MKstate == true && DVstate == true) {
    digitalWrite(redled, LOW);
  }


//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  //RTC Works, Rain Scheduled, MK ok~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //MK ON for 5s
  if(RTCstate == true && MistTimeState == true && MKstate == true) {
    digitalWrite(MK, LOW);
    delay(5000);
    digitalWrite(MK, HIGH);
  }
  //RTC Works, Rain Scheduled, MK No Water~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //Do nothing
  if(RTCstate == true && MistTimeState == true && MKstate == true) {
    digitalWrite(DV, HIGH);
  }
  
  //RTC Works, DHT Works, Humidity OK, No Rain, MK OK, DV OK~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //Do nothing
  if(RTCstate == true && DHTstate == true && Hstate == false && MistTimeState == false && MKstate == false && DVstate == false) {
  display.print("test");
  }
  
  //RTC Works
  /* Uncomment the OLED display part once conditions are added */

  display.display();
  

  delay(1000);
}

Could you tell us more about the DS3231 RTC? Is it an Adafruit module? Could you post a picture of it?

If you disconnect the RTC from the circuit entirely, and comment out any related code, does everything else work?

Inputs/outputs not shown in setup.......

Do you have a link to the origin of this sketch?

The RTC I have is this one https://www.amazon.ca/DS3231-Precision-Module-Arduino-Raspberry/dp/B07GRRBB8B/ref=sr_1_7?keywords=arduino+rtc&qid=1704748759&sr=8-7, I'm not sure if this fully answers your question.

Evaluating the modifications you mentioned, removing the RTC related lines in the program without removing the RCT module from the pins, the program froze later than with the code. When I removed the RTC from the circuit, it seems to be running continuously. In both cases, when I remove the

  display.begin(0x3C);
  display.setRotation(3);
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE,SH110X_BLACK);

from the loop and only place it in the setup, the program and display freeze like before.

I made the sketch using the RTClib, Adafruit SH110X (featherwing example), and DHT libraries

Thanks for letting me know, completely forgot about that

The RTC module looks fine. I'm assuming you have pullup resistors somewhere on the SDA and SCL lines. It doesn't look like the RTC module has any, but the display might.

I think the first thing is to make sure that each of the three devices is connected properly and is working. You can do that by running example sketches found in the libraries - one at a time, with only the relevant device connected to the circuit. When all three are working, then you can start in on your own software.

It's a good thing you pointed out your assumption. I don't know what pullup resistors are, my circuit wiring currently doesn't have any resistors.
This is what the circuit currently looks like

As for the individual sensor tests, all of the individual components work with example eketches of the libraries

Well if all three devices work independently, then there must be pullup resistors somewhere on SDA and SCL. Or perhaps Wire uses the internal pullup resistors. on A4 and A5.

I'm not able to help on your code. I don't know anything about the display or the temp sensor, or any of the libraries you are using, and just don't have the time to get up to speed on all that.

1 Like

When you compile your program, how much RAM does the compile process say you're using? I dug into the code behind Adafruit_SS1107 and saw that it was allocating a further 1K buffer at runtime. The Nano only has 2K of RAM to start with, so if your sketch shows it using anywhere near 1K when it compiles... you could be running out of RAM.

If that's the case, there is a text only library you could switch too. And if that's not in the cards, you could instruct the compiler to keep all your string literals you're printing in FLASH memory rather than in RAM by enclosing them in F(), like so:

display.print(F("T:"));

The upload message I get is the following, not sure if the dynamic memory represents the ram:

Sketch uses 18414 bytes (59%) of program storage space. Maximum is 30720 bytes.
Global variables use 657 bytes (32%) of dynamic memory, leaving 1391 bytes for local variables. Maximum is 2048 bytes.

For the font library, does text only usually include numbers too or only letters? (I still have to check the fonts in the GFX library)

So after the 1K buffer is uploaded, you've still got 367 bytes (18%) of RAM left. That wouldn't usually be a problem. It wouldn't hurt to move all those string literals out of RAM though. You mentioned adding more text to be output causing the lockup; you might just be right on the edge.

And all fonts will have at least the full ASCII set. Letters, numbers, punctuation, the works.

1 Like

Ah ok, how did you calculate or obtain the 18% RAM remaining?

Also, I forgot to mention that I tried enclosing the strings with the F() and everything froze again (though it lasted longer than the previous codes). For the font select, I'll need to see how to set the font with the library and I'll give an update on the results.

You've got 2048 bytes of RAM to start with.
Your sketch uses 657 bytes for global variables.
The library uses 1024 bytes for its screen buffer.

2048 - 657 - 1024 = 367 bytes left
100 * 367 / 2048 = 18% left

1 Like

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