I’m using an Arduino Uno for a little project with an SSD1306 OLED (connected to the SCL and SDA pins of the Arduino Uno, the ones above D13). I’m making an interactive menu to display on the OLED and using an SE055 encoder to interact with it. The code runs perfectly fine until a certain point where I try to add one more sub-menu; when I add the sub-menu code and I upload the code, the OLED for some reason doesn’t allocate.
This code runs perfectly:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//Encoder connections to Arduino digital ports
int A = 2; //DT
int B = 4; //CLK
int C = 3; //SW
//For the turnings of the encoder
int previous = 0;
int current = 0;
#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 -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int menu = 4; //0 = temperature option, 1 = humidity option, 2 = pressure option, 3 = altitude option, 4 = language menu, 5 = main menu; Starts in language menu when turned on.
int language = 0; //0 = english/inglés, 1 = spanish/español
int menuOption = 0; //0 = temperature, 1 = humidity, 2 = pressure, 3 = altitude, 4 = language
//Special characters
char letter1 = 164; //ñ
char letter2 = 162; //ó
char downArrow = 31; //▼
char upArrow = 30; //▲
void setup() {
pinMode(A, INPUT);
pinMode(B, INPUT);
pinMode(C, INPUT_PULLUP);
Serial.begin(9600);
//pins 2 & 3 have interrupts
attachInterrupt(digitalPinToInterrupt(A), encoder, LOW);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.setTextSize(1); // Normal 1:1 pixel scale, 21 chars fit horizontally, 8 vertically
display.setTextColor(WHITE); // Draw white text
display.cp437(true); // Use full 256 char 'Code Page 437' font
languageMenu();
}
void loop() {
//When the encoder is turned
if (current != previous) {
current = previous;
switch (menu) {
case 4:
languageMenu(); break;
case 5:
mainMenu(); break;
}
}
//When the encoder is pressed
if (digitalRead(C) == LOW) {
while (digitalRead(C) == LOW) {} //So the encoder has to stop being pressed to advance
if (menu == 4) {
menu++;
mainMenu();
}
while (digitalRead(C) == LOW) {} //Maybe redundant, I'll take care of this later
}
}
//For the interruptor (when the encoder turns)
void encoder() {
static unsigned long lastInterruption = 0;
unsigned long interruption = millis();
if (interruption - lastInterruption > 5) {
if (digitalRead(B) == HIGH) {
//Move cursor up
current--;
if (menu == 4) language--;
else if (menu == 5) menuOption--;
} else {
//Move cursor down
current++;
if (menu == 4) language++;
else if (menu == 5) menuOption++;
}
lastInterruption = interruption;
//for looping around the menus' options
if (language > 1) language = 0;
else if (language < 0) language = 1;
if (menuOption > 4) menuOption = 0;
else if (menuOption < 0) menuOption = 4;
}
}
void languageMenu() {
display.clearDisplay();
display.setCursor(0, 0);
if (language == 0) {
display.print("\n Choose Language\n Elija Lenguaje");
display.print("\n\n >English Espa");
display.print(letter1);
display.print("ol");
} else {
display.print("\n Choose Language\n Elija Lenguaje");
display.print("\n\n English >Espa");
display.print(letter1);
display.print("ol");
}
display.display();
}
void mainMenu() {
display.clearDisplay();
display.setCursor(0, 0);
if (language == 0) {
switch (menuOption) {
case 0:
display.print(" > Temperature\n\n");
display.print(" Humidity\n\n");
display.print(" Pressure\n\n");
display.print(" Altitude\n ");
display.print(downArrow); break;
case 1:
display.print(" Temperature\n\n");
display.print(" > Humidity\n\n");
display.print(" Pressure\n\n");
display.print(" Altitude\n ");
display.print(downArrow); break;
case 2:
display.print(" Temperature\n\n");
display.print(" Humidity\n\n");
display.print(" > Pressure\n\n");
display.print(" Altitude\n ");
display.print(downArrow); break;
case 3:
display.print(" Temperature\n\n");
display.print(" Humidity\n\n");
display.print(" Pressure\n\n");
display.print(" > Altitude\n ");
display.print(downArrow); break;
case 4:
display.print(" ");
display.print(upArrow);
display.print("\n > Language"); break;
}
} else {
switch (menuOption) {
case 0:
display.print(" > Temperatura\n\n");
display.print(" Humedad\n\n");
display.print(" Presi");
display.print(letter2);
display.print("n\n\n");
display.print(" Altitud\n ");
display.print(downArrow); break;
case 1:
display.print(" Temperatura\n\n");
display.print(" > Humedad\n\n");
display.print(" Presi");
display.print(letter2);
display.print("n\n\n");
display.print(" Altitud\n ");
display.print(downArrow); break;
case 2:
display.print(" Temperatura\n\n");
display.print(" Humedad\n\n");
display.print(" > Presi");
display.print(letter2);
display.print("n\n\n");
display.print(" Altitud\n ");
display.print(downArrow); break;
case 3:
display.print(" Temperatura\n\n");
display.print(" Humedad\n\n");
display.print(" Presi");
display.print(letter2);
display.print("n\n\n");
display.print(" > Altitud\n ");
display.print(downArrow); break;
case 4:
display.print(" ");
display.print(upArrow);
display.print("\n > Lenguaje"); break;
}
}
display.display();
}
void tempMenu() {
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(2);
display.write("Temperature here");
display.display();
display.setTextSize(1);
delay(10000);
mainMenu();
}
The display works without problems and I get this after compiling:
Sketch uses 15368 bytes (47%) of program storage space. Maximum is 32256 bytes.
Global variables use 884 bytes (43%) of dynamic memory, leaving 1164 bytes for local variables. Maximum is 2048 bytes.
However, when I add an else if to the “encoder is pressed” part of the loop (which now looks like this:)
//When the encoder is pressed
if (digitalRead(C) == LOW) {
while (digitalRead(C) == LOW) {} //So the encoder has to stop being pressed to advance
if (menu == 4) {
menu++;
mainMenu();
//Added segment
} else if (menu == 5) {
menu = menuOption;
switch (menuOption) {
case 0:
tempMenu();
}
}
//End of added segment
while (digitalRead(C) == LOW) {} //Maybe redundant, I'll take care of this later
}
The OLED doesn’t allocate anymore after running it (I get “SSD1306 allocation failed” in the Serial monitor).
The compiler gives me this:
Sketch uses 15502 bytes (48%) of program storage space. Maximum is 32256 bytes.
Global variables use 902 bytes (44%) of dynamic memory, leaving 1146 bytes for local variables. Maximum is 2048 bytes.
I’m pretty new with the Arduino stuff so I have no idea what is going on. Maybe it has something to do with the memory, even though I’m only using 48% of it? If anybody can see the problem, I’d greatly appreciate the help. Thanks.