OLED freezes Nano on display() call

Hi,
I am trying to control an 128x32 OLED using the Adafruit SSD1306 libary. This is my setup code:

void setup() {
  Serial.begin(9600);
  Serial.println(F("Started"));
  delay(1000);
  pinMode(MOTOR_RELAIS_PIN, OUTPUT);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }
  delay(2000);
  Serial.println(F("Display connected"));

  // display.setFont(&FreeSerif9pt7b);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  Serial.println(freeMemory());
  display.display();
  Serial.println(F("Display refresh"));

  dht.begin();
  Serial.println(F("DHT connected"));
}

The whole Arduino freezes when I reach the display.display() line. The screen shows a bunch of noise. The Serial.println(freeMemory()); gives me 963 Bytes of free memory which should be plenty enough as I think (maybe there is the problem) that the 1024 Bytes for the display buffer are already allocated when calling display.begin().

Thanks in advance for any help.

Show all your code, not just a snippet.

Show us a schematic, even a hand drawn one.

Are you using Arduino NANO or Nano ESP32?

How much dynamic memory (ram) does the IDE show when you compile the code? Add 1024 to this amount to account for the display buffer.

How are you determining this? If you are seeing the freeMemory amount printed in the serial monitor, you are well past the display.display() line that immediately follows. Put Serial.flush() after each line that you send to Serial, that will wait for the serial buffer to empty before continuing to the next line of code.

NANO with ATmega 328P processor

The IDE says that there are 566 bytes used. I know that it freezes at the display.display() line because freeMemory is shown but "Display refresh" isn't on the Serial Monitor.

Can you post the entire sketch?

Show all your code, not just a snippet.

#include <MemoryFree.h>
#include "DHT.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define DHT_PIN 3
#define DHT_TYPE DHT11
#define DISPLAY_POWER_PIN 5
#define MOTOR_RELAIS_PIN 6
#define ANA_POT_PIN 0

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 32  // OLED display height, in pixels
#define DISPLAY_TIMEOUT_MS 1000
#define POT_SAMPLE_RATE 200

// Size 32x32
const unsigned char temperature_icon_bitmap [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x04, 0x20, 0x00, 
	0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x20, 0x00, 
	0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x20, 0x00, 
	0x00, 0x04, 0x20, 0x00, 0x00, 0x05, 0xa0, 0x00, 0x00, 0x05, 0xa0, 0x00, 0x00, 0x05, 0xa0, 0x00, 
	0x00, 0x05, 0xa0, 0x00, 0x00, 0x05, 0xa0, 0x00, 0x00, 0x05, 0xa0, 0x00, 0x00, 0x0d, 0xb0, 0x00, 
	0x00, 0x19, 0x98, 0x00, 0x00, 0x33, 0xcc, 0x00, 0x00, 0x26, 0x64, 0x00, 0x00, 0x6c, 0x36, 0x00, 
	0x00, 0x68, 0x16, 0x00, 0x00, 0x68, 0x16, 0x00, 0x00, 0x6c, 0x36, 0x00, 0x00, 0x27, 0xe4, 0x00, 
	0x00, 0x33, 0xcc, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00
};

// Size 28x28
const unsigned char drop_icon_bitmap [] PROGMEM = {
	0x00, 0x06, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x19, 0x80, 0x00, 
	0x00, 0x39, 0xc0, 0x00, 0x00, 0x30, 0xc0, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0xe0, 0x70, 0x00, 
	0x00, 0xc0, 0x30, 0x00, 0x01, 0xc0, 0x38, 0x00, 0x01, 0x80, 0x18, 0x00, 0x03, 0x00, 0x0c, 0x00, 
	0x03, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x03, 0x00, 
	0x0c, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x0c, 0x00, 0x1b, 0x00, 
	0x0c, 0x00, 0x33, 0x00, 0x06, 0x00, 0x76, 0x00, 0x06, 0x00, 0xe6, 0x00, 0x03, 0x00, 0xcc, 0x00, 
	0x03, 0x80, 0x1c, 0x00, 0x01, 0xe0, 0x78, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x1f, 0x80, 0x00
};

// 'fan(1)', 32x32px
const unsigned char fan_icon_bitmap [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 
	0x00, 0x06, 0x18, 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x08, 0x01, 0x00, 
	0x03, 0x88, 0x0f, 0x00, 0x06, 0x8c, 0x18, 0x00, 0x04, 0x84, 0x30, 0x00, 0x08, 0xc4, 0x20, 0x00, 
	0x08, 0x64, 0x43, 0x80, 0x10, 0x33, 0xde, 0x70, 0x10, 0x0e, 0x60, 0x10, 0x10, 0x04, 0x20, 0x08, 
	0x10, 0x04, 0x20, 0x08, 0x08, 0x06, 0x70, 0x08, 0x0e, 0x7b, 0xcc, 0x08, 0x01, 0xc2, 0x26, 0x10, 
	0x00, 0x04, 0x23, 0x10, 0x00, 0x0c, 0x21, 0x20, 0x00, 0x18, 0x31, 0x60, 0x00, 0xf0, 0x11, 0xc0, 
	0x00, 0x80, 0x10, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x18, 0x60, 0x00, 
	0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

DHT dht(DHT_PIN, DHT_TYPE);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

unsigned long dht_last_read = 0;
unsigned long pot_last_read = 0;
int humidity = 100;
int temperature = 0;
int pot_val = 0;
int humidity_last_val = 0;
unsigned long humidity_last_change = 0;
int set_humidity = 50;
int new_set_humidity = 50;
bool motor_on = false;
bool display_pot = false;

void refreshDisplay(int temp, int hum) {
  display.clearDisplay();
  display.setTextSize(1);
  display.drawBitmap(-9,0, temperature_icon_bitmap, 32, 32, WHITE);
  display.drawBitmap(59,3, drop_icon_bitmap, 28, 28, WHITE);
  display.setCursor(21,6);
  display.setTextSize(3);
  display.print(temp);
  display.setCursor(91, 6);
  display.print(hum);
  display.display();
}

void showPotDisplay(int set_hum) {
  display.clearDisplay();
  display.drawBitmap(0,0, fan_icon_bitmap, 32, 32, WHITE);
  display.setCursor(40,6);
  display.setTextSize(3);
  display.println(set_hum);
  display.display();
}


void setup() {
  Serial.begin(9600);
  Serial.println(F("Started"));
  delay(1000);
  pinMode(MOTOR_RELAIS_PIN, OUTPUT);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }
  delay(2000);
  Serial.println(F("Display connected"));

  // display.setFont(&FreeSerif9pt7b);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  Serial.println(freeMemory());
  display.display();
  Serial.println(F("Display refresh"));
  dht.begin();
  Serial.println(F("DHT connected"));
}

void loop() {
  if (millis() > pot_last_read + POT_SAMPLE_RATE){
    pot_val = analogRead(ANA_POT_PIN);
    new_set_humidity = map(pot_val, 1023, 0, 0, 20);
    set_humidity = new_set_humidity * 5;
    pot_last_read = millis();
  }
  
  if (millis() > dht_last_read + 2000) {
    float new_humidity = dht.readHumidity();
    float new_temperature = dht.readTemperature();
    if (!isnan(new_humidity)) {
      humidity = new_humidity;
      Serial.println(F("Read hum"));
    }
    if (!isnan(new_temperature)) {
      temperature = new_temperature;
      Serial.println(F("Read temp"));
    }
    dht_last_read = millis();

    Serial.print(F("Pot Val: "));
    Serial.println(pot_val);
    Serial.print(F("Set hum: "));
    Serial.println(set_humidity);
    Serial.print(F("Hum: "));
    Serial.println(humidity);
  }

  if (set_humidity != humidity_last_val) {
    humidity_last_change = millis();
    humidity_last_val = set_humidity;
  }

  if (millis() > humidity_last_change + DISPLAY_TIMEOUT_MS) {
    display_pot = false;
  }
  else {
    display_pot = true;
  }

  if (display_pot) {
    showPotDisplay(set_humidity);
  }
  else {
    refreshDisplay(temperature, humidity);
  }

  if (humidity > set_humidity) {
    motor_on = true;
  } else {
    motor_on = false;
  }

  digitalWrite(MOTOR_RELAIS_PIN, motor_on);
}

Show us a schematic, even a hand drawn one.

See above

Correction on my previous post, a 128x32 display uses a 512 byte buffer.

I don't get any problems with the code locking up here. There is a two-second period of random pixels on the display because of your 2000mS delay between initializing the display and clearing it.

What type of relay are you using? Driving a relay directly from an output pin would only work for extremely low-current relays (below 40mA maximum, and that much is questionable), and needs a diode across the relay coil to avoid destroying the arduino.

The whole code works perfectly when not pluging in the display and the relay is switching so I do not think that is where the issue is comming from, but I can look up the data sheet of the relay.

Only spec i could find was the Coil Resitance at 125 Ohms resulting in exactly 40mA of current at 5V.
I have used these relays before and it always worked without any issues.

I would at least try running the sketch with the relay disconnected, it may be that the regulator on-board the Nano cannot handle the current from both the relay and the display.

Tried it, same result.

I would suggest to carry out the following steps to see the potential problem with your project.

1. Connect only the OLED (Fig-1) display unit with Arduino NANO using I2C Bus, 5V, and GND.
image
Figure1:

2. Upload the following test sketch (your one with some modification) for the OLED. Check that Hello! has appeared on the OLED. (Tested on my Arduino NANO.)

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET -1
Adafruit_SSD1306 display(128, 32, &Wire, OLED_RESET);

void setup()
{
  Serial.begin(9600);
  delay(1000);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
  {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }
  delay(2000);
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(10, 10);
  display.println("Hello!");
  display.display();
}

void loop() {}

3. Now connect your dht11 sensor with NANO, acquire signals and show on OLED.

Okay I have tested the display on a breadboard and it works fine so I guess it is a problem with my wiring although I checked if all the wires were connected and if there were any shorts so I don't really know where to look further but I'll check everything again

Have you uploaded the sketch of post #15 and saw the message Hello! on the display unit? If yes, then connect the dht11 sensor and report the result.

It was indeed a wiring issue. Although I checked about 10 times that all the wires are connected fo some reason I missed the 5V for the display. I wonder how it even displayed anything. Anyways it is working well now, thanks everyone for your help!

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