Code stops working after I uncomment a string declaration

I suspect it might be a memory overflow of somekind but I'm really not sure

Here is my code:

#include <Adafruit_GFX.h>
#include <ClickEncoder.h>
#include <TimerOne.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Variables
const int rotarySpeed = 4;
int itemsNum = 7;
const int mainNum = 7;
String mainMenu[7] = {"PAUSE", "MOTOR_1", "MOTOR_2", "MOTOR_3", "MOTOR_4", "UNIT", "RESET"};
const int unitNum = 3;
//String asd = "asd";
//String unitMenu[3] = {"RPM", "STEP/MIN", "MILILITER/MIN"};
const int motorNum = 4;
String motorMenu[4] = {"SPEED", "STOP", "START", "BACK"};
String menuItems[7];
int selectedItem = 0;
int selectedPos = 0;
boolean paused = false;

ClickEncoder *encoder;
int16_t last, value;

void timerIsr() {
  encoder->service();
}

void setup() {
  memcpy(menuItems, mainMenu, sizeof(mainMenu));
  Serial.begin(9600);

  encoder = new ClickEncoder(3, 2, 4);
  encoder->setAccelerationEnabled(false);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();

  Timer1.initialize(1000);
  Timer1.attachInterrupt(timerIsr);

  last = encoder->getValue();
}

void loop() {
  ClickEncoder::Button b = encoder->getButton();
  if (b != ClickEncoder::Open) {
    switch (b) {
      case ClickEncoder::Clicked:
        buttonPressed();
        break;
    }
  }
  value += encoder->getValue();
  if (round(value / rotarySpeed) % itemsNum < 0) {
    selectedItem = itemsNum + (value / rotarySpeed % itemsNum);
  } else {
    selectedItem = round(value / rotarySpeed) % itemsNum;
  }
  if (value / rotarySpeed > last) {
    //down
    last = value / rotarySpeed;
    if (selectedPos == 0) {
      selectedPos = 1;
    } else if (selectedPos == 1) {
      selectedPos = 2;
    }

  } else   if (value / rotarySpeed < last) {
    //up
    last = value / rotarySpeed;
    if (selectedPos == 2) {
      selectedPos = 1;
    } else if (selectedPos == 1) {
      selectedPos = 0;
    }
  }
  drawMenu();

  Serial.print(selectedItem);
  Serial.print(", ");
  Serial.print(selectedPos);
  Serial.print(", ");
  Serial.print(value);
  Serial.print(", ");
  Serial.print((value / rotarySpeed) % itemsNum);
  Serial.println();

  delay(10);
}

void buttonPressed() {
  if (true) {
    switch (selectedItem) {
      case 0:
        paused = true;
        break;
      case 1:
        memcpy(menuItems, motorMenu, sizeof(motorMenu));
        itemsNum = motorNum;
        selectedPos = 0;
        break;
      case 2:
        memcpy(menuItems, motorMenu, sizeof(motorMenu));
        itemsNum = motorNum;
        selectedPos = 0;
        break;
      case 3:
        memcpy(menuItems, motorMenu, sizeof(motorMenu));
        itemsNum = motorNum;
        selectedPos = 0;
        break;
      case 4:
        memcpy(menuItems, motorMenu, sizeof(motorMenu));
        itemsNum = motorNum;
        selectedPos = 0;
        break;
      case 5:
        //memcpy(menuItems, unitMenu, sizeof(unitMenu));
        //itemsNum = unitNum;
        selectedPos = 0;
        break;
      case 6:
        //reset
        break;
    }
  }

}

void drawMenu() {
  display.clearDisplay();
  display.setTextColor(BLACK, WHITE);
  display.setCursor(0, 0);
  display.setTextSize(2);
  display.print("MENU");
  display.setTextSize(1);
  if (selectedPos == 0) {
    display.setTextColor(BLACK, WHITE);
    display.setCursor(0, 16);
    display.print(menuItems[selectedItem]);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 32);
    display.print(menuItems[(selectedItem + 1) % itemsNum]);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 48);
    display.print(menuItems[(selectedItem + 2) % itemsNum]);
  }
  if (selectedPos == 1) {
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 16);
    if (selectedItem == 0) {
      display.print(menuItems[itemsNum - 1]);
    } else {
      display.print(menuItems[selectedItem - 1]);
    }
    display.setTextColor(BLACK, WHITE);
    display.setCursor(0, 32);
    display.print(menuItems[selectedItem]);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 48);
    display.print(menuItems[(selectedItem + 1) % itemsNum]);
  }
  if (selectedPos == 2) {
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 16);
    if (selectedItem <= 1) {
      display.print(menuItems[itemsNum + (selectedItem - 2) % itemsNum]);
    } else {
      display.print(menuItems[selectedItem - 2]);
    }
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 32);
    if (selectedItem == 0) {
      display.print(menuItems[itemsNum - 1]);
    } else {
      display.print(menuItems[selectedItem - 1]);
    }
    display.setTextColor(BLACK, WHITE);
    display.setCursor(0, 48);
    display.print(menuItems[selectedItem]);
  }
  display.display();
}

If I uncomment the line: String unitMenu[3] = {"RPM", "STEP/MIN", "MILILITER/MIN"}; the code stops working completely but if I only uncomment the line above it a strange glitch appears in the bottom right corner of the screen. (Picture attached)

The purpose of this code is a small menu navigatable by a rotary encoder.

Why are you using String for menu titles?

String motorMenu[4]
...
...
memcpy(menuItems, motorMenu,

Why?

TheMemberFormerlyKnownAsAWOL:
Why are you using String for menu titles?

String motorMenu[4]

...
...
memcpy(menuItems, motorMenu,


Why?

Should I use somethiung else? What should I use? I just needed an array with all the titles to make the code simpler. But I don't think thats what causes the issue.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

...R

For example, 'Serial.println("hello world");' is not printing a String. It's printing a cstring constant.

Thank you soo much!

Declaring them this way solved it :slight_smile:

const int rotarySpeed = 4;
int itemsNum = 7;
const int mainNum = 7;
char *mainMenu[7] = {"PAUSE", "MOTOR_1", "MOTOR_2", "MOTOR_3", "MOTOR_4", "UNIT", "RESET"};
const int unitNum = 3;
char *unitMenu[3] = {"RPM", "STEP/MIN", "MILILITER/MIN"};
const int motorNum = 4;
char *motorMenu[4] = {"SPEED", "STOP", "START", "BACK"};
char *menuItems[7];
int selectedItem = 0;
int selectedPos = 0;
boolean paused = false;