1

I hope this the right place to post this question :)

I'm trying to display a menu on a SSD1351 OLED display, to which I communicate with U8glib. I'm trying to obtain an Init screen, then, with a long press on a button (Menu), get in to a menu with 3 options (let's say option1, option2 and back). I got it working this way:

#include <Button.h>  // https://github.com/JChristensen/Button.git
#include "U8glib.h"
#include <Wire.h>

#define PULLUP true
#define INVERT true
#define DEBOUNCE_MS 20

Button ok(2, PULLUP, INVERT, DEBOUNCE_MS);
Button menu(5, PULLUP, INVERT, DEBOUNCE_MS);
Button down(3, PULLUP, INVERT, DEBOUNCE_MS);
Button up(4, PULLUP, INVERT, DEBOUNCE_MS);
U8GLIB_SSD1351_128X128_332 u8g(8, 9, 7);
uint8_t screen = 0;
uint8_t menu_current = 0;
void setup() {
  u8g.setFont(u8g_font_unifont);
  u8g.setDefaultForegroundColor();
  drawScreen();
}

void loop() {
  ok.read();
  menu.read();
  up.read();
  down.read();
  if (menu.pressedFor(1000) && screen == 0) {
    screen = 1;
    menu_current = 0;
    drawScreen();
  }
  if (screen == 1) {
    if (up.wasReleased()) {
      if (menu_current > 0) {
        menu_current--;
        drawScreen();
      }
    }
    if (down.wasReleased()) {
      if (menu_current < 2) {
        menu_current++;
        drawScreen();
      }
    }
    if (ok.wasReleased()) {
      switch (menu_current) {
        case 0:
          screen = 2;
          break;
        case 1:
          screen = 3;
          break;
        case 2:
          screen = 0;
          break;
          break;
      }
      drawScreen();
    }
  }
  if (screen == 2 || screen == 3) {
    if (menu.wasReleased()) {
      screen = 1;
      menu_current = 0;
      drawScreen();
    }
  }
}

void drawScreen() {
  u8g.firstPage();
  do {
    whatToDraw();
  } while (u8g.nextPage());
}

void whatToDraw() {
  switch (screen) {
    case 0: {
        u8g.drawStr(0, u8g.getFontLineSpacing(), F("Init"));
      } break;
    case 1: {
      const char *menu_strings[3] = { "option1", "option2", "Back" };
      uint8_t i, h;
      u8g_uint_t w, d;
      u8g.setFontRefHeightText();
      u8g.setFontPosTop();
      h = u8g.getFontAscent() - u8g.getFontDescent();
      w = u8g.getWidth();
      for ( i = 0; i < 3; i++ ) {
        d = (w - u8g.getStrWidth(menu_strings[i])) / 2;
        u8g.setDefaultForegroundColor();
        if ( i == menu_current ) {
          u8g.drawBox(0, i * h + 1, w, h);
          u8g.setDefaultBackgroundColor();
        }
        u8g.drawStr(d, i * h, menu_strings[i]);
      }
    }
    break;
    case 2: {
      u8g.drawStr(0, u8g.getFontLineSpacing(), F("Option1"));
    }
    break;
    case 3: {
      u8g.drawStr(0, u8g.getFontLineSpacing(), F("Option2"));
    }
    break;
    break;
  }
}

Everything seems to be working except the back option: when I select it, the display gets blanked instead of visualizing screen 0 ("Init"). Variables seem to be set correctly. Does anybody have an idea why this isn't working?

Thank you :)

Dario

EDIT: copied the whole sketch as requested :)

dda
  • 1,553
  • 1
  • 12
  • 17
noospy
  • 11
  • 1
  • 5
  • Please, post your whole sketch, so others can test your code. –  Jul 22 '17 at 17:54
  • I don't see any back option; only up, down, ok and menu. What button was that? –  Jul 22 '17 at 18:29
  • I didn't define a back back physical button. "Back" is one of the options visualized in the menu. I'd like to be able to select it (highlight it with up and down buttons) and click the Ok button, to revert to Init screen :) – noospy Jul 22 '17 at 18:38
  • Correct me. Your test case is: screen 0; press menu; screen 1; press down; press down; Press OK over option BACK and then screen goes blank? –  Jul 22 '17 at 20:00
  • I only miss an `u8g2.begin()`, but all your execution paths include a `drawScreen()` call, and you always put something in the screen. You don't modify global vars inside de `drawScreen()` and it's the only place where you touch the screen. Good problem. –  Jul 22 '17 at 20:12
  • Yes, that's exactly my test case :) if I try to print the variables in serial monitor, everything seems to be working fine, but the display blanks out... – noospy Jul 22 '17 at 22:27
  • The only way to get a blank screen is when `screen` is out of range. Just to be sure, why don't you check its value upon entry into `whatToDraw`. I run your sketch in a simulation and your logic is OK. –  Jul 22 '17 at 23:55
  • BTW, I'm using u8g2, the new version. I tried to compile your code using the new library, and it didn't like using `F("init")` as argument. It accepts the simple string "init", however. May be there is a bug in your version, so change `F("init")`for `"init"`(and every other use of `F()`). May be ... –  Jul 23 '17 at 00:36
  • @LookAlterno I tried to remove the 'F()' caption but nothing changed.. I also tried to remove the 'u8g.getFontLineSpacing()' but nothing changed too :( Then I tried to print on serial the 'screen' variable and, in the test case, it correctly prints '0' but I keep having this problem. I'd like to solve it, but a workaround would be cool too.. Thank you :) – noospy Jul 23 '17 at 16:59

2 Answers2

1

Summary: I tested @noospy project (with some modifications) and it works flawlessly.

Menu and buttons

I had to rename Button.h to ButtonM.h due name conflict with another button library. Also, I'm using new version U8g2, so I had to change some types and eliminate some calls. Finally, I used the I2C version of the OLED screen.

This is my adapted code:

#include <ButtonM.h>  // https://github.com/JChristensen/Button.git
#include "U8g2lib.h"
#include <Wire.h>

#define PULLUP true     
#define INVERT true    
#define DEBOUNCE_MS 20   

Button ok(2, PULLUP, INVERT, DEBOUNCE_MS);  
Button menu(5, PULLUP, INVERT, DEBOUNCE_MS);
Button down(3, PULLUP, INVERT, DEBOUNCE_MS);
Button up(4, PULLUP, INVERT, DEBOUNCE_MS);

//U8GLIB_SSD1351_128X128_332 u8g(8, 9, 7);
// Screen
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

uint8_t screen = 0;
uint8_t menu_current = 0;

void setup() {    
    u8g.begin(); // Added
    u8g.setFont(u8g_font_unifont);       
//  u8g.setDefaultForegroundColor();

    drawScreen(); 
}

void loop() {
    ok.read();
    menu.read();
    up.read();
    down.read();

    if (menu.pressedFor(1000) && screen == 0) {       
        screen = 1;    
        menu_current = 0;
        drawScreen();
    }

    if (screen == 1) {
        if (up.wasReleased()) {       
            if (menu_current > 0) {
                menu_current--;
                drawScreen();
            }
        }

        if (down.wasReleased()) {       
            if (menu_current < 2) {
                menu_current++;
                drawScreen();
            }
        }

        if (ok.wasReleased()) {       
            switch (menu_current) {          
                case 0: 
                    screen = 2;
                    break;
                case 1:
                    screen = 3;
                    break;
                case 2:
                    screen = 0;
                    break;
                break;
            }
            drawScreen();
        }
    }

    if (screen == 2 || screen == 3) {
        if (menu.wasReleased()) {
            screen = 1;
            menu_current = 0;
            drawScreen();
        }
    }
}

void drawScreen() {
    u8g.firstPage();  
    do {
        whatToDraw();
    } while( u8g.nextPage() );
}

void whatToDraw() {
    switch (screen) {
        case 0: {                           
            u8g.drawStr(0,getFontLineSpacing(),"Init");
        } break;
        case 1: {   
            const char *menu_strings[3] = { "option1", "option2", "Back" };
            uint8_t i, h;
            int w, d;

            u8g.setFontRefHeightText();
            u8g.setFontPosTop();

            h = u8g.getFontAscent()-u8g.getFontDescent();
            w = u8g.getWidth();
            for( i = 0; i < 3; i++ ) {
                d = (w-u8g.getStrWidth(menu_strings[i]))/2;
//                u8g.setDefaultForegroundColor();
                if ( i == menu_current ) {
                    u8g.drawBox(0, i*h+1, w, h);
//                    u8g.setDefaultBackgroundColor();
                }
                u8g.drawStr(d, i*h, menu_strings[i]);
            }
         } break;

         case 2: {                         
             u8g.drawStr(0,getFontLineSpacing(),"Option1");
         } break;

         case 3: {                        
             u8g.drawStr(0,getFontLineSpacing(),"Option2");
         } break;

         break;
    }
}

int getFontLineSpacing() {
  return 24;
}

Hardware

  1. Arduino Pro Mini 3.3v 8MHz
  2. 1306 0.96 inch White Color I2C IIC Communication 128 * 64 OLED Display.
  3. 4x push buttons with 1K pullup resistors.

So, I don't know what your problem is, but your code is impecable.

  • Thank you! Well, at least now I know it's not a coding issue. I'll try with your same hardware and report back! – noospy Jul 25 '17 at 19:09
0

You can consider using one of the existing menu libraries, there are some available on github. Just pick the one that best fits your needs

https://github.com/search?utf8=%E2%9C%93&q=arduino+menu&type=

neu-rah
  • 149
  • 5