1

I need some hand here. I wrote some code for a small arduino console-like device that has five pushbuttons, 128x64 I2C OLED display and arduino nano. And it doesn't work when uploaded to arduino nano - display goes blank.

Anamnesis: The Code includes two classes: menu class and button class. When I upload the code on my device - it doesn’t display anything on oled but arduino still executes the code. Wiring is not an issue. But when I remove games_menu or pongLevel_menu or settings_menu and sound_menu from class objects and comment lines where these objects are used, the code works just fine.

Question: Maybe the thing is that arduino nano has some kind of memory, where it stores class objects, and my code uses too much of this memory. Since I am kinda new to arduino and programming - I can make mistakes. Can you please help me with this problem? Minimum reproducible code (sorry, I know that it looks like a big chunk of code but that's what I can shrink it to so that it still reproduces the problem):

#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
Adafruit_SSD1306 display(128, 64, &Wire, -1);
//------------variables-------------
    //--------menu variables--------
    unsigned long sec;
    byte selY = 12;
    boolean up;
    boolean down;
    boolean left;
    boolean right;
    boolean a;
    boolean b;
    int location = 0;
    
    //--------stopwatch variables--------
    unsigned long startTime;
    bool stTimeB = 1;
    unsigned long millisec;
    byte seconds;
    byte minutes;
    byte hours;
//--------classes-------
    //----class menu----
    class menu {
    public:
      menu(String caption, String item1, String item2, String item3, String item4, unsigned int minn, unsigned int maxx);
      void play();
      
    private:
     String cap;
     String it1;
     String it2;
     String it3;
     String it4;
     unsigned int _min;
     unsigned int _max;
  };
  menu::menu(String caption, String item1, String item2, String item3, String item4, unsigned int minn, unsigned int maxx){
    cap = caption;
    it1 = item1;
    it2 = item2;
    it3 = item3;
    it4 = item4;
    _min = minn;
    _max = maxx;
    
    }
  
  void menu::play(){
    if(up == 1 && millis() - sec > 199){
      selY -= 10;
      sec = millis();
    }
    if(down == 1 && millis() - sec > 199){
      selY += 10;
      sec = millis();
    }
    if(selY < _min){
      selY = _max;
    }
    if(selY > _max){
      selY = _min;
    }
    
    display.clearDisplay();
    display.setTextSize(1); 
    display.setTextColor(WHITE); 
    display.setCursor(50, 0);  
    display.print(cap);
    display.drawLine(0, 9, 128, 9, WHITE);
    display.setCursor(6, 13);  
    display.print(it1);
    display.setCursor(6, 23);  
    display.print(it2);
    display.setCursor(6, 33);  
    display.print(it3);
    display.setCursor(6, 43);  
    display.print(it4);
    display.drawRoundRect(1, selY, 122, 11, 4, WHITE);
    display.display();
    
  }
    //--------class button--------
    class button {
  public:
    button(byte xx, byte yy, byte rr, byte var, String caption11, String caption22, String type_, byte tSize);
    void disp();
    void changeCap(bool caption);
    bool getStatus();
    void update_();
    

  private:
   byte x;
   byte y;
   byte r;
   byte txtSize;
   bool capB = 0; // 1
   bool pres = 0;
   byte btnPin;
   String caption1;
   String caption2;
   String type;
};
button::button(byte xx, byte yy, byte rr, byte var, String caption11, String caption22, String type_, byte tSize){
  x = xx;
  y = yy;
  r = rr;
  btnPin = var;
  caption1 = caption11;
  caption2 = caption22;
  type = type_;
  txtSize = tSize;
  }

void button::disp(){
  display.setTextSize(txtSize);
  if(pres == 0){
    display.drawRoundRect(x, y, (((caption1.length() + 2)*(5*txtSize)) + (caption1.length() - 1)), ((7+4)*txtSize), r, WHITE); 
    display.setTextColor(WHITE);
  }
  else{
    display.fillRoundRect(x, y, (((caption2.length() + 2)*(5*txtSize)) + (caption2.length() - 1)), ((7+4)*txtSize), r, WHITE);
    display.setTextColor(BLACK);
  }
  
  
  if(pres == 0){display.setTextColor(WHITE); }
  if(pres == 1){display.setTextColor(BLACK);}
  
  if(capB == 0){
    if(pres == 1){display.setTextColor(BLACK);}
    if(pres == 0){display.setTextColor(WHITE);}
    display.setCursor(x+(5*txtSize), y+(2*txtSize));
    display.print(caption1);
  }
  else{
    display.setCursor(x+(5*txtSize), y+(2*txtSize));
    display.print(caption2);
  }
}

bool button::getStatus(){
  return pres;
}
void button::update_(){
  if(type == "push_button"){
    if(!digitalRead(btnPin) == 1 && millis() - sec > 19){
      pres = 1;
      sec = millis();
    }
    if(!digitalRead(btnPin) == 0){
      pres = 0;
    }
  }
  if(type == "switch"){
    if(!digitalRead(btnPin) == 1 && millis() - sec > 189){
      pres = !pres;
      sec = millis();
    }
  }
}

void button::changeCap(bool captionB){
  capB = captionB;
}
//--------class objects--------
menu main_menu("main", "games", "stopwatch", "timer...", "settings", 12, 42);
    menu games_menu("games", "pong", "guess a number...", " ", " ", 12, 22);
      menu pongLevel_menu("level", "easy", "hard", "expert", "impossible ", 12, 42);
    menu settings_menu("settings", "sound", "credits", " ", " ", 12, 22);
        menu sound_menu("sound", "on", "off", " ", " ", 12, 22);
      
button startB(25, 32, 6, 14, "start", "stop", "switch", 2);

//--------functions-----------
void buttonsUpdate(){
  up = !digitalRead(A0);
  down = !digitalRead(A2);
  left = !digitalRead(12);
  right = !digitalRead(A1);
  a = !digitalRead(4);
}
void resetTime(){ 
    millisec = 0;
    seconds = 0;
    minutes = 0;
    hours = 0;
}
void cookTime(){ // logic for stopwatch and calcuulating milliseconds, seconds, minutes and hours 
  startB.update_();
  if(startB.getStatus() == 1){startB.changeCap(1);digitalWrite(13,1);}
  if(startB.getStatus() == 0){startB.changeCap(0);stTimeB = 1;digitalWrite(13,0);}
 
  if(startB.getStatus() == 1){
    if(stTimeB == 1){resetTime(); startTime = millis(); stTimeB = 0; }
    millisec = ((millis()-startTime)/10) % 100;
    seconds = ((millis()-startTime)/1000)%60;
    minutes = ((millis()-startTime)/(1000*60))%60;
    hours = ((millis()-startTime)/(1000*60*60))%60;
  }
}

void dispStopwatch(){ // display stopwatch
  cookTime();
  display.clearDisplay(); 
  startB.disp();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(8, 10);
  display.print(hours);
  display.print("|");
  display.print(minutes);
  display.print("|");
  display.print(seconds);
  display.print("|");
  display.print(millisec);
  display.display();
}

void setup() {
  Wire.begin();
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay(); 
  pinMode(13, OUTPUT); 
  // buttons' pins setup
  pinMode(A0, INPUT_PULLUP); // up
  pinMode(A1, INPUT_PULLUP); // right
  pinMode(12, INPUT_PULLUP); // left
  pinMode(A2, INPUT_PULLUP); // down

  pinMode(4, INPUT_PULLUP);  // a
 }

void loop() {
 buttonsUpdate();
  if(up == 1 && down == 1){location = 0;}
  
  if(location == 0){//main menu
    main_menu.play(); 
    if(a == 1 && selY == 12/*if a btn is clicked while selected first item*/ && millis() - sec > 199){location = 1/*games*/; sec = millis();}
    if(a == 1 && selY == 22/*if a btn is clicked while selected first second*/ && millis() - sec > 199){location = 2/*stopwatch*/; sec = millis();}
    //if(a == 1 && selY == 32 && millis() - sec > 199){location = 3/*timer*/; sec = millis();}
    if(a == 1 && selY == 42/*if a btn is clicked while selected first fourth*/ && millis() - sec > 199){location = 4/*settings*/; sec = millis();}
  }

  if(location == 1){//game menu
        games_menu.play();
        if(a == 1 && selY == 12 && millis() - sec > 199){location = 11/*pong*/; sec = millis();}
      }
          if(location == 11){//pong levels
          pongLevel_menu.play();
          }
  
  if(location == 2){//stopwatch
        dispStopwatch();
  }
  if(location == 4){//settings
        settings_menu.play();
        if(a == 1 && selY == 12 && millis() - sec > 199){location = 41/*sound*/; sec = millis();}
        if(a == 1 && selY == 22 && millis() - sec > 199){location = 42/*credits*/; sec = millis();}
      }
          if(location == 41){// sound menu
            sound_menu.play();
          }
          if(location == 42){// credits
           // drawBitmap();
          }
}
6
  • 1
    Please put your code into the question. Also what is that link? To a comment on SE with another link to a different question on SE?
    – chrisl
    May 31 at 10:33
  • I tried to put code but it separates some lines and writes it as text. Link is to stack Overflow where code can pase normaly
    – Demko
    May 31 at 11:25
  • Responders on StackOverflow have already suggested you make use of Flash memory to reduce the amount of the (very limited) RAM your code needs. Some additional suggestions: Strings often fragment available RAM into unusably small pieces; C strings - null-terminated character arrays - are much more RAM-friendly. Any constants, constant strings, constant members of objects, can be moved to Flash too, to free more of the limited RAM. Search "PROGMEM Arduino" for tutorials. Practice with them until you can apply the principles to your code.
    – JRobert
    May 31 at 11:40
  • 1
    Link is to stack Overflow where code can pase normaly ... the code parses the same way here ... read Syntax highlighting for code here arduino.stackexchange.com/editing-help ...
    – jsotola
    May 31 at 15:07
  • 1
    I have copied the code. But please delete the question on stackoverflow. Multi-postings is frowned upon. Jul 17 at 11:30

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.