Array in combination with Adafruit_SSD1306

Bit stumped here. I'm trying to build a menu and display it. For some reason the application will not work when Oled and array. If I remove all Oled related initialization, the Array works, if I add Oled I can't get past Setup(). Following code works (serial shows hello and logo draws:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "MenuHandler.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)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#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 NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ 0b00000000, 0b11000000,
  0b00000001, 0b11000000,
  0b00000001, 0b11000000,
  0b00000011, 0b11100000,
  0b11110011, 0b11100000,
  0b11111110, 0b11111000,
  0b01111110, 0b11111111,
  0b00110011, 0b10011111,
  0b00011111, 0b11111100,
  0b00001101, 0b01110000,
  0b00011011, 0b10100000,
  0b00111111, 0b11100000,
  0b00111111, 0b11110000,
  0b01111100, 0b11110000,
  0b01110000, 0b01110000,
  0b00000000, 0b00110000 };


void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

}

void loop() {
  Serial.println("hello"); 
 /* for (int j=0; j<2; j++) {
    Serial.println("getting current Menu");
    currentMenu = menus[j];

    for (int i=0; i<currentMenu.getNumItems(); i++) {
     Serial.print("4.item Name: "); Serial.print(currentMenu.getItem(i).getName()); Serial.println(currentMenu.getItem(i).getId()); 
    }
  }
  */
  delay(500);
  
}

Now if I add the following statement to the code

#include "Menu.h"

const String _ActionHome = "Home Z";
const String _SubMoveZ = "Move Menu";
const String _ActionMove = "Move Z";
const String _ActionEdge = "Edge find";
const String _ActionBurn = "Burn";
const String _ActionStatus = "Status";
const String _ActionMoveSegment = "MoveSeg";
const String _ActionBack = "Back";

Menu currentMenu;
Menu mainMenu = Menu(0, "main");
Menu moveMenu = Menu(1, "move Z");
Menu menus[2];

Specifically the statement Menu menus[2]; breaks it all.

If I remove all Oled specific code the array works just fine.

what's your arduino? do you have enough memory?

where does MenuHandler.h come from?

Arduino Micro, can't imagine running out memory this quick: The MenuHandler.h I wrote myself. It basically builds two menus with menu items on each menu.

Sketch uses 17640 bytes (61%) of program storage space. Maximum is 28672 bytes.
Global variables use 1277 bytes (49%) of dynamic memory, leaving 1283 bytes for local variables. Maximum is 2560 bytes.

#include "Menu.h"

const String _ActionHome = "Home Z";
const String _SubMoveZ = "Move Menu";
const String _ActionMove = "Move Z";
const String _ActionEdge = "Edge find";
const String _ActionBurn = "Burn";
const String _ActionStatus = "Status";
const String _ActionMoveSegment = "MoveSeg";
const String _ActionBack = "Back";

Menu currentMenu;
Menu mainMenu = Menu(0, "main");
Menu moveMenu = Menu(1, "move Z");
Menu menus[2];


void createMenu(){
  Serial.print("inside Create Menu a "); //DEBUGGING

//main menu items

  MenuItem item1 = MenuItem(0, "Home Z Axis");
  item1.addAction(_ActionHome);
  mainMenu.addMenuItem(item1);
 
  MenuItem item2 = MenuItem(1, "Move Z Axis");
  item2.addSubMenu(moveMenu.getId());
  mainMenu.addMenuItem(item2);
  
  MenuItem item3 = MenuItem(2, "Edge Find");
  item3.addAction(_ActionEdge);
  mainMenu.addMenuItem(item3);
  
  MenuItem item4 = MenuItem(3, "Burn");
  item4.addAction(_ActionBurn);
  mainMenu.addMenuItem(item4);
  
  MenuItem item5 = MenuItem(4, "Status");
  item5.addAction(_ActionStatus);
  mainMenu.addMenuItem(item5);

// move menu items 
  MenuItem item6 = MenuItem(0, "0.001");
  item6.addAction(_ActionMoveSegment);
  moveMenu.addMenuItem(item6);
  
  MenuItem item7 = MenuItem(1, "0.01");
  item7.addAction(_ActionMoveSegment);
  moveMenu.addMenuItem(item7);
  
  MenuItem item8 = MenuItem(2, "0.1");
  item8.addAction(_ActionMoveSegment);
  moveMenu.addMenuItem(item8);
  
  MenuItem item9 = MenuItem(3, "1");
  item9.addAction(_ActionMoveSegment);
  moveMenu.addMenuItem(item9);
  
  MenuItem item10 = MenuItem(4, "10");
  item10.addAction(_ActionMoveSegment);
  moveMenu.addMenuItem(item10);

  menus[0] = mainMenu;
  menus[1] = moveMenu;
  
  currentMenu = mainMenu;
  
}

At the end I add the two menus to an array of menu, so I can loop over them.

You need 128x64 bits or 1 KiB for the display buffer, and then some more for the Strings and the stack, so it's very likely that you're running out of memory.

1 Like

your local variables (like item1, item2, ...) get deallocated when you exit the createMenu() function
what does the mainMenu.addMenuItem() do ? create a copy ?

Did you know that even an empty String consumes six bytes of RAM?

Does you menu handler make excessive use of Strings?

each menuitem is added to an array of menuitems on Menu at the end of createMenu the two menus are added to a global array of menu Menu menus[2] (the array that is causing issue). If I comment out the instantiation of the Oled stuff and only call createMenu() from the setup(), I can loop over the array and nothing is de-alocated.


void setup() {
  Serial.begin(9600);
/*
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();
*/

createMenu();
}

void loop() {
 // Serial.println("hello"); 
  for (int j=0; j<2; j++) {
    Serial.println("getting current Menu");
    currentMenu = menus[j];

    for (int i=0; i<currentMenu.getNumItems(); i++) {
     Serial.print("4.item Name: "); Serial.print(currentMenu.getItem(i).getName()); Serial.println(currentMenu.getItem(i).getId()); 
    }
  }
 
  delay(500);
  
}

Serial Monitor:

12:52:47.656 -> getting current Menu
12:52:47.656 -> 4.item Name: 0
12:52:47.656 -> 4.item Name: 1
12:52:47.656 -> 4.item Name: 2
12:52:47.656 -> 4.item Name: Burn3
12:52:47.656 -> 4.item Name: 4
12:52:47.656 -> getting current Menu
12:52:47.656 -> 4.item Name: 0.0010
12:52:47.656 -> 4.item Name: 0.011
12:52:47.656 -> 4.item Name: 0.12
12:52:47.656 -> 4.item Name: 13
12:52:47.656 -> 4.item Name: 104
12:52:48.168 -> getting current Menu
12:52:48.168 -> 4.item Name: 0
12:52:48.168 -> 4.item Name: 1
12:52:48.168 -> 4.item Name: 2
12:52:48.168 -> 4.item Name: Burn3
12:52:48.168 -> 4.item Name: 4
12:52:48.168 -> getting current Menu
12:52:48.168 -> 4.item Name: 0.0010
12:52:48.168 -> 4.item Name: 0.011
12:52:48.168 -> 4.item Name: 0.12
12:52:48.168 -> 4.item Name: 13
12:52:48.168 -> 4.item Name: 104
12:52:48.676 -> getting current Menu
12:52:48.676 -> 4.item Name: 0
12:52:48.676 -> 4.item Name: 1
....

you probably store a copy of the local variable. hard to say without all the code.
I still think you should investigate memory challenges

I'll start removing Strings where I can. will try again

any chance you could modify your menu code to deal with Strings in PROGEM rather than RAM?

removed all string definitions and used char[] and pointers instead. it works now.

#ifndef MenuItem_h
#define MenuItem_h

#include <Arduino.h>


class MenuItem {
 public:
  MenuItem();
  MenuItem(int id, char* name); //was String
  void addAction(int act);
  void addSubMenu(int id);
  boolean isAction();
  boolean isSubMenu();
  int getId();
  char* getName();
  String getNameStr();
 
 private:
  int _id;
  char* _name; //was String
  int _action;
  int _subMenuId;
  boolean _isAction = false;
  boolean _isSubMenu = false;
};

instantiation now looks like this:

const char* HomeZAxis = "Home Z Axis";
const char* MoveZAxis = "Move Z Axis";
const char* EdgeFind = "Edge Find";
const char* Burn = "Burn";
const char* Status = "Status";

const char* i10 = "10";
const char* i1 = "1";
const char* i01 = "0.1";
const char* i001 = "0.01";

const char* back = "Back";


Menu currentMenu;
Menu mainMenu = Menu(0, "main");
Menu moveMenu = Menu(1, "move Z");
Menu menus[2];


void createMenu(){
  Serial.print("inside Create Menu a "); //DEBUGGING

//main menu items

  MenuItem item1 = MenuItem(0, HomeZAxis);
  item1.addAction(_ActionHome);
  mainMenu.addMenuItem(item1);
 
  MenuItem item2 = MenuItem(1, MoveZAxis);
  item2.addSubMenu(moveMenu.getId());
  mainMenu.addMenuItem(item2);
  
  MenuItem item3 = MenuItem(2, EdgeFind);
  item3.addAction(_ActionEdge);
  mainMenu.addMenuItem(item3);
  
  MenuItem item4 = MenuItem(3, Burn);
  item4.addAction(_ActionBurn);
  mainMenu.addMenuItem(item4);

Thx!!

great news !

you are probably very close to the memory limit. using PROGMEM and (__FlashStringHelper *) could probably help you save ~100 bytes of RAM

1 Like

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