Display.begin or softwareSerial crashing Arduino?

Hi all, this is my first post so please inform me of any potential mistakes I'm making.

The appended sketch (that I have already reduced to the minimum for this error) compiles without issues for an Arduino Nano with a ATmega328P (Old bootloader, doesn't work on new bootloader at all).
However, when uploading the sketch or resetting the Nano, the setup is only running to the display.begin(i2c_Address, true); line and (according to the serial monitor, which should count up the loops) crashes and restarts, which is observable in the Serial Monitor.

If I now comment out either the paragraph for the display (lines 123-127) OR the lines for the VESC, which uses softwareSerial (lines 20, 117, 118, 148 and 202-217), the code runs flawlessly, but is without much use to me. For context: VESC is a kind of motor speed controller.

I have read this StackOverflow-thread which blames an overflowing buffer, but was unable to find one aswell as this one which says that RAM is running out. ยด While I find that to be the more obvious answer, I'm unable to confirm this (and I have no idea how to).

Any help with this issue would be greatly appreciated. If there are any major issues in my coding, I'd happily receive feedback.

Thank you all in advance!

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <VescUart.h>
#include <SoftwareSerial.h>

//Adresses
#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1   //   QT-PY / XIAO
#define rxPin 5
#define txPin 4

//Objects
VescUart vesc;
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
SoftwareSerial vescSerial = SoftwareSerial(rxPin, txPin); // RX, TX

//Variables
int i = 1;

int PotiWert;
int GasProzent;
int vescNunchuk;

int Drehzahl;
int Eingangsspannung;
int Amperestunden;
int Tachometer;

const int Gyro1 = 0x68;
const int Gyro2 = 0x69;

float AccXHolm, AccYHolm, AccZHolm;
float gAccXHolm, gAccYHolm, gAccZHolm;
float AngleXHolm, AngleYHolm;
float AccXBrett, AccYBrett, AccZBrett;
float gAccXBrett, gAccYBrett, gAccZBrett;
float AngleXBrett, AngleYBrett;

const unsigned char MobiliTechLogo [] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x03, 0xc7, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00,
  0x1c, 0x00, 0x38, 0x00, 0x01, 0xe0, 0x03, 0xef, 0x3c, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xf0, 0x00,
  0x3c, 0x00, 0x78, 0x00, 0x01, 0xe0, 0x01, 0xcf, 0x3d, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xf0, 0x00,
  0x1e, 0x00, 0x78, 0x00, 0x01, 0xe0, 0x00, 0x0f, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xf0, 0x00,
  0x1f, 0x00, 0xf8, 0x00, 0x01, 0xe0, 0x00, 0x0f, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0xf0, 0x00,
  0x1f, 0x00, 0xf8, 0x1f, 0x81, 0xef, 0x81, 0xcf, 0x3c, 0x07, 0x80, 0xfc, 0x01, 0xf8, 0xf3, 0xe0,
  0x1f, 0x81, 0xf8, 0x3f, 0xe1, 0xff, 0xe1, 0xcf, 0x3c, 0x07, 0x83, 0xfe, 0x07, 0xfc, 0xff, 0xf0,
  0x1f, 0x81, 0xf8, 0x7f, 0xf1, 0xff, 0xf1, 0xcf, 0x3c, 0x07, 0x87, 0xff, 0x0f, 0xfe, 0xff, 0xf8,
  0x1f, 0xc3, 0xf8, 0xf0, 0xf9, 0xf0, 0xf1, 0xcf, 0x3c, 0x07, 0x87, 0x87, 0x9f, 0x0e, 0xfc, 0x78,
  0x1d, 0xe7, 0xb8, 0xe0, 0x79, 0xe0, 0x79, 0xcf, 0x3c, 0x07, 0x8f, 0x03, 0x9e, 0x00, 0xf8, 0x38,
  0x1c, 0xe7, 0x39, 0xe0, 0x39, 0xe0, 0x79, 0xcf, 0x3c, 0x07, 0x8f, 0x03, 0x9c, 0x00, 0xf0, 0x3c,
  0x1c, 0xff, 0x39, 0xe0, 0x39, 0xe0, 0x79, 0xcf, 0x3c, 0x07, 0x8f, 0xff, 0x9c, 0x00, 0xf0, 0x3c,
  0x1c, 0x7e, 0x39, 0xe0, 0x39, 0xe0, 0x79, 0xcf, 0x3c, 0x07, 0x8f, 0xff, 0x9c, 0x00, 0xf0, 0x3c,
  0x1c, 0x7c, 0x39, 0xe0, 0x79, 0xe0, 0x79, 0xcf, 0x3c, 0x07, 0x8f, 0x00, 0x1e, 0x00, 0xf0, 0x3c,
  0x1c, 0x3c, 0x38, 0xf0, 0xf9, 0xf0, 0xf1, 0xcf, 0x3c, 0x07, 0x87, 0x82, 0x1e, 0x0c, 0xf0, 0x3c,
  0x1c, 0x18, 0x38, 0xff, 0xf1, 0xff, 0xf1, 0xcf, 0x3c, 0x07, 0x87, 0xff, 0x0f, 0xfe, 0xf0, 0x3c,
  0x3c, 0x00, 0x38, 0x7f, 0xe1, 0xff, 0xe1, 0xcf, 0x3c, 0x07, 0x83, 0xff, 0x07, 0xfc, 0xf0, 0x3c,
  0x1c, 0x00, 0x38, 0x1f, 0xc1, 0xcf, 0xc1, 0xcf, 0x3c, 0x07, 0x80, 0xfe, 0x03, 0xf8, 0xf0, 0x38,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void setup() {

  Serial.begin(9600);
  Serial.println("serial begun.");

  vescSerial.begin(19200);
  Serial.println("vescSerial begun.");

  Wire.begin();
  Serial.println("wire begun.");
  delay(250); //waiting for components to power up

  display.begin(i2c_Address, true);
  Serial.println("display begun.");
  display.clearDisplay();
  display.drawBitmap(0, 0,  MobiliTechLogo, 128, 64, 1);
  display.display();

  Wire.beginTransmission(Gyro1);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  Serial.println("gyro1 begun.");

  Wire.beginTransmission(Gyro2);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  Serial.println("gyro2 begun.");

}

void loop() {

  NeigungHolmMessen();
  NeigungBrettMessen();
  PotiMessen();
  VESCMessen();

  Serial.print("loop done x");
  Serial.println(i);
  i++;

  delay(1000);

}

void NeigungHolmMessen() {

  Wire.beginTransmission(Gyro1);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(Gyro1, 6, true);

  AccXHolm = (Wire.read() << 8 | Wire.read());
  AccYHolm = (Wire.read() << 8 | Wire.read());
  AccZHolm = (Wire.read() << 8 | Wire.read());
  gAccXHolm = AccXHolm / 16384;
  gAccYHolm = AccYHolm / 16384;
  gAccZHolm = AccZHolm / 16384;

  AngleXHolm = (atan(gAccYHolm / sqrt(pow(gAccXHolm, 2) + pow(gAccZHolm, 2))) * 180 / PI) - 0.58;
  AngleYHolm = (atan(-1 * gAccXHolm / sqrt(pow(gAccYHolm, 2) + pow(gAccZHolm, 2))) * 180 / PI) + 1.58;

}

void NeigungBrettMessen() {

  Wire.beginTransmission(Gyro1);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(Gyro1, 6, true);

  AccXBrett = (Wire.read() << 8 | Wire.read());
  AccYBrett = (Wire.read() << 8 | Wire.read());
  AccZBrett = (Wire.read() << 8 | Wire.read());
  gAccXBrett = AccXBrett / 16384;
  gAccYBrett = AccYBrett / 16384;
  gAccZBrett = AccZBrett / 16384;

  AngleXBrett = (atan(gAccYBrett / sqrt(pow(gAccXBrett, 2) + pow(gAccZBrett, 2))) * 180 / PI) - 0.58;
  AngleYBrett = (atan(-1 * gAccXBrett / sqrt(pow(gAccYBrett, 2) + pow(gAccZBrett, 2))) * 180 / PI) + 1.58;

}

void PotiMessen() {

  PotiWert = analogRead(A0);

}

void VESCMessen() {

  if ( vesc.getVescValues() ) {

    Serial.println(vesc.data.rpm);
    Serial.println(vesc.data.inpVoltage);
    Serial.println(vesc.data.ampHours);
    Serial.println(vesc.data.tachometerAbs);

  }
  else
  {
    Serial.println("Failed to get data!");
  }

}

Welcome to the forum.

The VESC library is written for the Teensy, which has a lot more memory than the classic Nano.

Can you copy the code of the function freeMemory() here: Measuring Memory Usage | Memories of an Arduino | Adafruit Learning System
and add it to the bottom of your sketch.

At the end of setup(), print the free memory.

void setup()
{
  ...

  Serial.println(freeMemory());
}

Welcome to the forum

const unsigned char MobiliTechLogo [] PROGMEM = {

The array is in PROGMEM and you cannot normally access data from PROGMEM unless you use special functions

  display.drawBitmap(0, 0,  MobiliTechLogo, 128, 64, 1);

Does this function expect to find the array in main memory or PROGMEM I wonder ?

As an experiment try declaring a much smaller bitmap without putting it in PROGMEM and see whether it works

When commenting out the display-portion of code, the value for freeMemory is 2299. With the softwareSerial and VescUart commented out, it's 313. That seems like a significant difference, although I don't really know what to do with this information.

(With the original code, it of course doesn't compile, but if I put freeMemory() before display.begin, it's at 2295, but probably doesn't really tell me anything)

Using a 8x8 bmp (see code), the program still didn't run past the display.begin. When using the freeMemory() function as Koepel described, the program has the same 2299 somethings (I guess bytes?).
I'm unsure if your question was rhetorical or not, but reloading a different bitmap (a 128x64 one) in the same way with a const unsigned char and writing it to PROGMEM has worked so far, and with some other code I scratched in order to keep the post minimal, displaying any image has never been the problem.

Display.begin() attempts to allocate half (1K bytes) of the available RAM memory on an ATmega328 for the display buffer, which is not revealed by the memory report published at the end of the compile/link step. You can avoid that by using the text only version of the library.

All lines like this needlessly take up RAM for string constant storage, as well:

 Serial.println("gyro2 begun.");

Replace all of them using the F macro, which forces the constant to be stored in program memory instead.

 Serial.println(F("gyro2 begun."));

Hi, thank you for pointing me to the F() macro, I'll try to remember that going forward.
While I had some issues using the suggested library at first (because I have a SH1106 instead of a SSD), I figured it out and it now works. I'll hesitantly mark this as a solution since I'm now missing the bitmap, but this is a very good alternative. Thank you all very much!

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