OLED crashes sketch

I’m working on a tide clock, right now just a clock. I have a 60 LED Neopixel ring controlled by a Nano. I have a real time clock module. I have it working to show a hour hand, 3 red LED’s, minute hand, 1 green LED, and a second hand, a blue LED. works fine. I’m now trying to add a 128 x 64 I2C OLED. When I try to display either the time or just text on the OLED the sketch crashes. I’ve checked that I don’t have an I2C address conflict between the RTC and the OLED.

I can run the Adafruit example, SSD1306_128x64, just fine by itself. I then added one of the test functions from that example into my sketch. It does work, although because of the for loops and delays in that function the second hand pauses, when the function is done the second hand advances. I then made a separate sketch to display a couple of incrementing values, also works fine. But when I replace the Adafruit function with the display sketch, as a function, to my program it gets hung up. I replaced the incrementing variables with just text, same thing. I added a Serial.print statement at the beginning of the function and when I open the serial monitor it only prints one half of the text.

I’m thinking it’s a timing or resource conflict but obviously I don’t know or wouldn’t be asking.

Thanks in advance, the code is below

// My test clock
// added OLED display

#include <FastLED.h> // FastSPI Library from http://code.google.com/p/fastspi/
#include <Wire.h> //This is to communicate via I2C. On arduino Uno & Nano use pins A4 for SDA (yellow/orange) and A5 for SCL (green). For other boards ee http://arduino.cc/en/Reference/Wire
#include <RTClib.h>           // Include the RTClib library to enable communication with the real time clock.
// Include Adafruit Graphics & OLED libraries
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

RTC_DS3231 RTC; // Establishes the chipset of the Real Time Clock

// Reset pin not used but needed for library
#define OLED_RESET 4
//Adafruit_SSD1306 display(OLED_RESET);
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define LEDStripPin 6 // Pin used for the data to the LED strip
#define menuPin 0 // Pin used for the menu button (green stripe)
#define numLEDs 60 // Number of LEDs in strip

// Setting up the LED strip
struct CRGB leds[numLEDs];

int timeHour;
int timeMin;
int timeSec;
int LEDOffset = 0;

long int updateTime = millis();
int updateDelay = 1000;


void setup() {

  // Start LEDs
  LEDS.addLeds<WS2811, LEDStripPin, GRB>(leds, numLEDs); // Structure of the LED data. I have changed to from rgb to grb, as using an alternative LED strip. Test & change these if you're getting different colours.
  LEDS.setBrightness(10);

  // Start RTC
  Wire.begin(); // Starts the Wire library allows I2C communication to the Real Time Clock
  RTC.begin(); // Starts communications to the RTC

  // initialize OLED with I2C addr 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  Serial.begin(9600); // Starts the serial communications

  // create a loop that calcuated the number of counted milliseconds between each second.
  DateTime now = RTC.now();

  Serial.print("Hour time is... ");
  Serial.println(now.hour());
  Serial.print("Min time is... ");
  Serial.println(now.minute());
  Serial.print("Sec time is... ");
  Serial.println(now.second());

  Serial.print("Year is... ");
  Serial.println(now.year());
  Serial.print("Month is... ");
  Serial.println(now.month());
  Serial.print("Day is... ");
  Serial.println(now.day());

} // end void setup

void loop() {

  DateTime now = RTC.now(); // Fetches the time from RTC

  // clear LED array
  memset(leds, 0, numLEDs * 3);

  unsigned char hourPos = ((now.hour() % 12) * 5 + (now.minute() + 6) / 12);

  leds[(hourPos + LEDOffset + 59) % 60].r = 255;
  leds[(hourPos + LEDOffset + 59) % 60].g = 0;
  leds[(hourPos + LEDOffset + 59) % 60].b = 0;
  leds[(hourPos + LEDOffset) % 60].r = 255;
  leds[(hourPos + LEDOffset) % 60].g = 0;
  leds[(hourPos + LEDOffset) % 60].b = 0;
  leds[(hourPos + LEDOffset + 1) % 60].r = 255;
  leds[(hourPos + LEDOffset + 1) % 60].g = 0;
  leds[(hourPos + LEDOffset + 1) % 60].b = 0;
  leds[(now.minute() + LEDOffset) % 60].r = 0;
  leds[(now.minute() + LEDOffset) % 60].g = 255;
  leds[(now.minute() + LEDOffset) % 60].b = 0;
  leds[(now.second() + LEDOffset) % 60].r = 0;
  leds[(now.second() + LEDOffset) % 60].g = 0;
  leds[(now.second() + LEDOffset) % 60].b = 255;

  // Update LEDs
  LEDS.show();


  if (millis() > (updateTime + updateDelay))
  {
    updateDisplay();
    updateTime = millis();

  } // end updateDisplay time


} // end void loop

void updateDisplay() {
  Serial.println("Update display");

  // Clear the display
  display.clearDisplay();
  //Set the color - always use white despite actual display color
  display.setTextColor(WHITE);
  //Set the font size
  display.setTextSize(2);
  //Set the cursor coordinates
  display.setCursor(0, 10);
  // display.print("Time");
  display.setCursor(0, 20);
  display.print("02:11:22");
  display.setCursor(0, 40);
  //  display.print("Date");
  display.setCursor(0, 50);
  display.print("3/4/21");

  display.display(); // Update screen


} // end updateDisplay

Serial.print("Hour time is... "); Needs more F(), like the rest of your literal constant prints, but I suspect this will be marginal.

I modified this line display.print("02:11:22"); to display.print(F("02:11:22")); I did the same for the other text lines I'm trying to display. The only thing it did was make the serial.print statement I have a the top of the function print the full text, it still didn't display the text on the OLED and it does make the clock stop.

Thanks for the suggestion

60 leds and the Adafruit OLED libraries, that uses a lot of ram.

Could you add the freeMemory() function to your sketch: Measuring Memory Usage | Memories of an Arduino | Adafruit Learning System.
Call it for example from the updateDisplay() function.

Can you test your sketch with one led ?

Did you know that OLED displays disturb the I2C bus for others, especially when a 5V Arduino board is used.
Only the Adafruit OLED modules are reliable with a 5V Arduino board.

The first thing in setup() could be printing something.

void setup()
{
  Serial.begin(9600); // Starts the serial communications
  Serial.println( "The sketch has started");
  ...
}

That puts the text in the TX buffer. While that is being send to the TX line in a interrupt, the sketch continues. If only a few characters show in the serial monitor, then you know that the sketch has crashed a few milliseconds after the call to Serial.println.

It's probably running out of memory.

As-is your sketch compiles and uses 911 bytes of RAM. However, the OLED buffer occupies another 1024-bytes of memory. You've also got 60 LEDs taking no less than 3 bytes each for 180-bytes: You've only got 2KB of RAM to work with; the static use the compiler picks up and the dynamic use of the LEDs and OLED means you're using all of it and then some.

That's it I'm running out of memory. I tried it with only 1 LED running and it didn't crash but didn't display my test. I then commented out all the LED references and now it displays the text.

A couple of questions. There are only 5 LEDs on at a time but I assume it makes a memory space for all 60, is that correct? I'll have to look at the specs for the other controllers but does a UNO or one of the others have enough memory? I'd like to stay with one of the smaller ones but I guess I could fit a Mega in there if that would work.

Thanks so much for your help and the education
John

Get a “nano every” - pin comparable , cheap and more memory !

I was just checking the specs and saw that, I'll give it a try

thanks

I have another question. When I compile the sketch that crashes the complier at the bottom states

Sketch uses 17782 bytes (57%) of program storage space. Maximum is 30720.
Global variables use 885 bytes (43%) of dynamic memory, leaving 1163 bytes for local variables. maximum is 2048.

But we've kind of proven that I am running out of memory. Is what is referenced above not the true amount, is there another memory that is full but not here, or is it a different problem than running out of memory?

I do have a mega I can try.

Thanks

The compiler/linker doesn’t and cannot know about memory allocated at run-time.

This is a completely incorrect use of millis():

  if (millis() > (updateTime + updateDelay))

Study a standard timing sketch like Blink without Delay to see how it's done.

First, the sketch does running the 60 LEDS as a clock and displays the time on the OLED with a Mega, again proving what you've said about memory, not that I doubted you. I'll try a Nano Every.

@aarg, I looked at the Blink without delay and it's a bit different but not by that much. My way is basically the same and it works. If you ask 3 programs to do something all the programs will work but differently. Is there something wrong with the way I'm doing it? Does it cause some other kind of a problem, similar to the original one I asked about?

Thanks for the help
John

If you ask 3 programs to do something all the programs will work but differently.

It depends on how long you are willing to wait to find out that you’re wrong.

Have a look at the u8g2 library, it has options that use less ram for the display buffer, particularly if you only want monochrome text with no graphics.

@david_2018, that's very interesting, I found the library and I'm reading about it now, I'll give it a try.

Thanks
John

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