Super weird problem : printing 7 or more characters to OLED crashes nano in boot

This is REALLY weird ! :o

Line 156 (line 12 up from the end) in the following code is display.println(“Load zero:”);. You’ll notice, it is commented out in the code below.

When commented out, the code compiles, uploads and runs just fine (Arduino nano v3 clone Joy-IT) – e.g. during setup (line 85’ish) the code flashes a number of adafruit dotstar LED’s, and displays some text on a .96" (128x64) OLED, etc.

However, if I uncomment line 156 to print ‘Load zero:’ to the OLED, the code compiles and uploads, but it never actually starts (e.g. no LED flashes durin setup).

Wait…, it gets weirder!

If I uncomment line 156, BUT keep the text to 6 characters or less: it compiles, uploads and runs

If the text exceeds 6 characters … same issue: Compiles, uploads, fails to run at all (no flashing LED’s)

I can also get it to work with several println lines, but the number of characters (incl line-feed) must not exceed 7 bytes).

Similarly, if I remove characters from an earlier display.println() command, I can add the same number of characters to line 156 without problems … there seems to be a maximum number of characters I can print after which it crashes the nano.

My first thought was, perhaps this is a problem with ram – I’ve seen that in a PC once which would crash during the boot sequence when it hit a particular RAM address. But this apparently never makes to line 156 at all IF line 156 prints 6+ characters.

Arduino reports, I’m using 61% of memory (sketch) and 41% of dynamic memory.

#include <HX711.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_DotStar.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// OLED display wiring
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);

// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 2;
const int LOADCELL_SCK_PIN = 3;
HX711 loadCell;


// Button wiring
const int BUTTON_PIN = 6;
int buttonState = 0;

// LED strip wiring
#define NUMPIXELS 9 // Number of LEDs in strip
#define DATAPIN    4
#define CLOCKPIN   5
Adafruit_DotStar strip(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BRG);

// Program
int i = 0; // counter
int program = 0; // 0: PPT test, 1: Calibrate
unsigned long starttime = 0;
unsigned long waittime = 1000;
int progressLineLength = 125;
int progressLineNext = 0;

int buttonWait (unsigned long waittime, int lineLength) {
  int buttonState = digitalRead(BUTTON_PIN);
  unsigned long starttime = millis();
  unsigned long nowtime = millis();
  int linePoint = 0;
  while ( (nowtime < starttime + waittime) && (buttonState == LOW)) {
    buttonState = digitalRead(BUTTON_PIN);
    linePoint = (nowtime - starttime)/(waittime / lineLength);
    display.setCursor(linePoint,0);
    display.println(".");
    display.display();
    nowtime = millis();
  }
  while (digitalRead(BUTTON_PIN) == HIGH) { delay(10); } // Wait for button release
  return buttonState;
}

void setup() {  
  Serial.begin(9600);
  
  // Setup OLED
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay(); 
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.println("Initializing..");
  display.display(); 

  // Setup HX711
  long loadCellZero = 50000000;
  long loadCellScale = 5000000;
  display.setCursor(0,10);
  display.println("..pressure sensor");
  display.display(); 
  loadCell.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  loadCell.set_scale(2500.f);
  loadCell.tare();

  // Setup button
  pinMode(BUTTON_PIN, INPUT);

  // Setup LED strip
  // display.clearDisplay(); display.display();
  display.setCursor(0,20);
  display.println("..LED strip");
  display.display(); 
  strip.begin(); // Initialize pins for output
  strip.show();  // Turn all LEDs off ASAP
  for (int i = 0; i < NUMPIXELS; i++) {
    strip.setPixelColor(i, 0xFFFFFF);
    strip.show();
  }
  delay(250);
  for (int i = 0; i < NUMPIXELS; i++) {
    strip.setPixelColor(i, 0x000000);
    strip.show();
  }

  // Wait for user to press button, to check button works
  display.setCursor(0,30);
  display.println("Check button now..");
  display.display(); 
  while (digitalRead(BUTTON_PIN) == LOW) { delay(10); }  // Wait for button press
  while (digitalRead(BUTTON_PIN) == HIGH) { delay(10); } // Wait for button release

  display.clearDisplay(); display.display();

  // Ask suer whether to calibrate
  // Run loop for a while (waittime) while waiting for button press
  display.setCursor(0,10);
  display.println("To calibrate...");
  display.setCursor(0,20);
  display.println("Press button now");
  display.display(); 
  Serial.println("Calibrate?");
  buttonState = buttonWait(2000, 128);
  display.clearDisplay(); display.display();

  // If button was pressed confirm choice to calibrate
  if (buttonState == HIGH) {
    Serial.println("Calibrate!");
    display.setCursor(0,10);
    display.println("Calibrating in 2 sec..");
    display.setCursor(0,20);
    display.println("To CONFIRM...");
    display.setCursor(0,30);
    display.println("Press button now");
    display.display();
    buttonState = buttonWait(2000,128);
    display.clearDisplay(); display.display();
  }
  // If button was pressed (again), do calibration
  if (buttonState == HIGH) {
    program = 1;
    Serial.println("Calibration confirmed.");
  } else {
    program = 0;
    Serial.println("Calibration cancelled.");
  }
}

void loop() {
  buttonState = digitalRead(BUTTON_PIN);
  
  if (program == 1) {
    display.setCursor(1,10);
    display.println("Calibrate UNLOADED.");
    display.setCursor(1,20);
    display.println("Keep algometer fixed.");
    display.setCursor(1,30);
    display.println("Press button...");
    display.setCursor(1,40);
    display.println("when ready.");
    display.display();
    while (digitalRead(BUTTON_PIN) == LOW) { delay(10); }  // Wait for button press
    while (digitalRead(BUTTON_PIN) == HIGH) { delay(10); } // Wait for button release
    //loadCellZero = loadCell.get_units(10);
    display.clearDisplay(); 
    display.setCursor(1,10);
    //display.println("Load zero:");
    display.setCursor(1,20);
    display.display();
    program = 0;
  }

  
  Serial.println(loadCell.get_units(), 1);
  if (buttonState == HIGH) {
    Serial.println(millis());
  }
}

Change all the statements that print() anonymous literal strings e.g.

  display.println("Initializing..");

to

  display.println(F("Initializing.."));

This will store the messages in Flash instead of wasting SRAM.

Note that you could have inspected the memory use in the Build report.
Remember that Adafruit_SSD1306 will steal an extra 1024 bytes of SRAM at runtime.

David.

Ach so ... that was a quick and helpful answer.

I thank you very much! :slight_smile:

It does indeed solve the issue