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,595
  • 1
  • 12
  • 17
noospy
  • 11
  • 1
  • 5

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.

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