Menu system on Teensy3 and OLED (SSD1306)

Status
Not open for further replies.

Dean

Member
Hi,

Can anyone offer any advice on any libraries out there I can use to implement a multi level menu system for an OLED screen, I would like to use 5 buttons, left, right, up, down and enter for navigation. I've tried googling but have not found anything out there.

If there are not any libraries if there are any projects with source code I can reverse engineer I'd love to find out.

This is the main part of my project and I will build upon the menu once it works smoothly, I will be happy to share my progress as it develops.

So any help would be greatly appreciated so I can get moving on my project, I'm feeling eager to get on with it.

The typical use would be

'=' Top Menu
'==' Sub Menu
'===' Menu item

Menu structure
= Main menu
== Set up
=== Set temp
=== Set time
== Display
=== Show temp
=== Show time
 
So I have managed to solve this myself, anyone else who is looking for basic code for a menu for a OLED here it is
Code:
/*
  OLED Menu System
  
  Created by Dean, 10th October 2013.
  
  Menu Library from http://jonblack.org/
  OLED Library from Adafruit
*/

#include <MenuSystem.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306h.h>

//DEFINES
#define OLED_DC 8
#define OLED_CS 10
#define OLED_CLK 13
#define OLED_MOSI 11
#define OLED_RESET 7
Adafruit_SSD1306h display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// Menu variables
MenuSystem ms;
Menu mm("");
Menu mu1("Display");
MenuItem mu1_mi1("Display1");
MenuItem mu1_mi2("Display2");
MenuItem mu1_mi3("Display3");
Menu mu2("Settings");
MenuItem mu2_mi1("Settings1");
MenuItem mu2_mi2("Settings2");
MenuItem mu2_mi3("Settings3");

// Example variables
const int UpBtn = 5;       // the number of the pushbutton pin
const int DownBtn = 4;     // the number of the pushbutton pin
const int SelectBtn = 3;   // the number of the pushbutton pin
const int BackBtn = 2;     // the number of the pushbutton pin
int UpButtonState = 0;     // variable for reading the pushbutton status
int DownButtonState = 0;   // variable for reading the pushbutton status
int SelectButtonState = 0; // variable for reading the pushbutton status
int BackButtonState = 0;   // variable for reading the pushbutton status
bool bRanCallback = false;
bool bForward = true;
int line = 10;             // variable for setting display line

// Menu callback function
// In this example all menu items use the same callback.

void on_display1_selected(MenuItem* p_menu_item)
{
  //Serial.println("DISPLAY1 Selected");
  display.setCursor(0,55);
  display.print("DISPLAY1 Selected");
  bRanCallback = true;
  bForward = true;
}
void on_display2_selected(MenuItem* p_menu_item)
{
  //Serial.println("DISPLAY2 Selected");
  display.setCursor(0,55);
  display.print("DISPLAY2 Selected");
  //bRanCallback = false;
  bForward = true;
}
void on_display3_selected(MenuItem* p_menu_item)
{
  //Serial.println("DISPLAY3 Selected");
  display.setCursor(0,55);
  display.print("DISPLAY3 Selected");
  bRanCallback = false;
  bForward = true;
}

void on_settings1_selected(MenuItem* p_menu_item)
{
  //Serial.println("SETTINGS1 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS1 Selected");
  bRanCallback = true;
  bForward = true;
}
void on_settings2_selected(MenuItem* p_menu_item)
{
  //Serial.println("SETTINGS2 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS2 Selected");
  bRanCallback = false;
  bForward = true;
}
void on_settings3_selected(MenuItem* p_menu_item)
{
  //Serial.println("SETTINGS3 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS3 Selected");
  //bRanCallback = false;
  bForward = true;
}

// Standard arduino functions

void setup()
{
  Serial.begin(9600);
  
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306h_SWITCHCAPVCC);
  
    // initialize the pushbutton pin as an input:
  pinMode(UpBtn, INPUT); 
    // initialize the pushbutton pin as an input:
  pinMode(DownBtn, INPUT); 
      // initialize the pushbutton pin as an input:
  pinMode(SelectBtn, INPUT); 
      // initialize the pushbutton pin as an input:
  pinMode(BackBtn, INPUT); 
  
  display.display(); 		// show splashscreen
  delay(2000);
  display.clearDisplay();   // clears the screen and buffer
  
// Menu setup
  mm.add_menu(&mu1);
  mu1.add_item(&mu1_mi1, &on_display1_selected);
  mu1.add_item(&mu1_mi2, &on_display2_selected);
  mu1.add_item(&mu1_mi3, &on_display3_selected);
  mm.add_menu(&mu2);
  mu2.add_item(&mu2_mi1, &on_settings1_selected);
  mu2.add_item(&mu2_mi2, &on_settings2_selected);
  mu2.add_item(&mu2_mi3, &on_settings3_selected);
  ms.set_root_menu(&mm);
}

void loop()
{
//OLED set up
  display.display(); 		
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  line=10; //line variable reset
  //Serial.println("");
  
  
// Display Title
  display.setCursor(0,0);
  display.println("MENU");
  
// Display the menu
  Menu const* cp_menu = ms.get_current_menu();
  MenuComponent const* cp_menu_sel = cp_menu->get_selected();
  for (int i = 0; i < cp_menu->get_num_menu_components(); ++i)
  {
    MenuComponent const* cp_m_comp = cp_menu->get_menu_component(i);
    //Serial.print(cp_m_comp->get_name());
    display.setCursor(30,line);
    display.print(cp_m_comp->get_name());
    
    if (cp_menu_sel == cp_m_comp){
      //Serial.print("<<< ");
      display.setCursor(0,line);
      display.print(">>> ");
    }
    line=line+10;
    //Serial.println("");
  } 
 
// read the state of the pushbutton value:
  UpButtonState = digitalRead(UpBtn);
  if (UpButtonState == HIGH) {    
    ms.prev(); 
  } 
  
  DownButtonState = digitalRead(DownBtn);
  if (DownButtonState == HIGH) {   
    ms.next();  
  } 

  SelectButtonState = digitalRead(SelectBtn);
  if (SelectButtonState == HIGH) {   
    ms.select();  
  } 
  
  BackButtonState = digitalRead(BackBtn);
  if (BackButtonState == HIGH) {   
    ms.back();  
  } 
 
  
// Wait for two seconds so the output is viewable
  delay(500);
}

Library is available from http://jonblack.org/2012/05/14/arduino-library-for-creating-a-menu-system/
 
Last edited:
Next on the list,

How to get the buttons to work as interrupts?
and add a better way of displaying output notice i.e display.print("DISPLAY2 Selected");
 
Hello
If it's possible, please, post <MenuSystem.h> for this code. The download link, it's not working.
Thank you in advance.
 
Help!

Hello of Dean! Can you help me? Немогу to add a new menu item. Can you describe more detailed description? How to add the menu item? Already week I sit above a code. Below my code.

PHP:
#include <MenuSystem.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

//Пины
#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// Menu variables
MenuSystem ms;
Menu mm("");
Menu mu1("Display");
MenuItem mu1_mi1("Display1");
MenuItem mu1_mi2("Display2");
MenuItem mu1_mi3("Display3");
Menu mu2("Settings");
MenuItem mu2_mi1("Settings1");
MenuItem mu2_mi2("Settings2");
MenuItem mu2_mi3("Settings3");
Menu mu3("Ethernet");
MenuItem mu3_mi1("Set1");
MenuItem mu3_mi2("Set2");
MenuItem mu3_mi3("Set3");

// Объявления переменных и констант
const int buttonPin = 0;   // аналоговый вход для кнопок

int buttonValue = 0;   // переменная для значения АЦП кнопки
int UpButtonState = 0;     // переменная для кнопки вверх
int DownButtonState = 0;   // переменная для кнопки вниз
int SelectButtonState = 0; // переменная для кнопки выбора
int BackButtonState = 0;   // переменная для кнопки возврата

bool bRanCallback = false;
bool bForward = true;

int line = 30;             // переменная для установки настроек в линию


// Функция меню обратного вызова
// В этом примере все пункты меню можно использовать для обратного вызова.

void on_display1_selected(MenuItem* p_menu_item)
{
  Serial.println("DISPLAY1 Selected");
  display.setCursor(0,55);
  display.print("DISPLAY1 Selected");
  bRanCallback = true;
  bForward = true;
}
void on_display2_selected(MenuItem* p_menu_item)
{
  Serial.println("DISPLAY2 Selected");
  display.setCursor(0,55);
  display.print("DISPLAY2 Selected");
  //bRanCallback = false;
  bForward = true;
}
void on_display3_selected(MenuItem* p_menu_item)
{
  Serial.println("DISPLAY3 Selected");
  display.setCursor(0,55);
  display.print("DISPLAY3 Selected");
  bRanCallback = false;
  bForward = true;
}

void on_settings1_selected(MenuItem* p_menu_item)
{
  Serial.println("SETTINGS1 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS1 Selected");
  bRanCallback = true;
  bForward = true;
}
void on_settings2_selected(MenuItem* p_menu_item)
{
  Serial.println("SETTINGS2 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS2 Selected");
  bRanCallback = false;
  bForward = true;
}
void on_settings3_selected(MenuItem* p_menu_item)
{
  Serial.println("SETTINGS3 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS3 Selected");
  //bRanCallback = false;
  bForward = true;
}

void on_set1_selected(MenuItem* p_menu_item)
{
  Serial.println("SETTINGS1 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS1 Selected");
  bRanCallback = true;
  bForward = true;
}
void on_set2_selected(MenuItem* p_menu_item)
{
  Serial.println("SETTINGS2 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS2 Selected");
  bRanCallback = false;
  bForward = true;
}
void on_set3_selected(MenuItem* p_menu_item)
{
  Serial.println("SETTINGS3 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS3 Selected");
  //bRanCallback = false;
  bForward = true;
}
// Standard arduino functions

void setup()
{
  Serial.begin(9600);
  
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC);
  
  
  display.display(); 		// show splashscreen
  delay(1000);
  display.clearDisplay();   // clears the screen and buffer
  
// Menu setup
  mm.add_menu(&mu1);
  
  mu1.add_item(&mu1_mi1, &on_display1_selected);
  mu1.add_item(&mu1_mi2, &on_display2_selected);
  mu1.add_item(&mu1_mi3, &on_display3_selected);
  
  mm.add_menu(&mu2);
  
  mu2.add_item(&mu2_mi1, &on_settings1_selected);
  mu2.add_item(&mu2_mi2, &on_settings2_selected);
  mu2.add_item(&mu2_mi3, &on_settings3_selected);
  
  mm.add_menu(&mu3);
  
  mu3.add_item(&mu3_mi1, &on_set1_selected);
  mu3.add_item(&mu3_mi2, &on_set2_selected);
  mu3.add_item(&mu3_mi3, &on_set3_selected);
  
  ms.set_root_menu(&mm);
}

void loop()
{
  buttonValue = analogRead(buttonPin);
  Serial.println(buttonValue);
  
//OLED set up
  display.display(); 		
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  line=15; //line variable reset
  Serial.println("//OLED set up");
  
  
// Display Title

  display.setCursor(10,0);
  display.println("MENU CONFIGURATION");
  display.setCursor(0,5);
  display.print("_____________________");
  display.setCursor(110,15);
  Serial.println("//OLED");
 
// Display the menu
  Menu const* cp_menu = ms.get_current_menu();
  MenuComponent const* cp_menu_sel = cp_menu->get_selected();
  for (int i = 0; i < cp_menu->get_num_menu_components(); ++i)
  {
    MenuComponent const* cp_m_comp = cp_menu->get_menu_component(i);
    Serial.println(cp_m_comp->get_name());
    display.setCursor(10,line);
    display.print(cp_m_comp->get_name());
    
    if (cp_menu_sel == cp_m_comp){
      Serial.print("<<< ");
      display.setCursor(0,line);
      display.write(16);
    }
    line=line+10;
    Serial.println("");
  } 
 
// read the state of the pushbutton value:
  UpButtonState = buttonValue;
  if (UpButtonState > 830 && UpButtonState < 840) {    
    ms.prev(); 
  } 
  
  DownButtonState = buttonValue;
  if (UpButtonState > 860 && UpButtonState < 870) {   
    ms.next();  
  } 

  SelectButtonState = buttonValue;
  if (UpButtonState > 480 && UpButtonState < 490) {   
    ms.select();  
  } 
  
  BackButtonState = buttonValue;
  if (UpButtonState > 319 && UpButtonState < 325) {   
    ms.back();  
  } 
 
  
// Wait for two seconds so the output is viewable
  delay(1500);
}
IMG_20150313_105735.jpg

And it is your working code

PHP:
#include <MenuSystem.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

//Пины
#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// Menu variables
MenuSystem ms;
Menu mm("");
Menu mu1("Display");
MenuItem mu1_mi1("Display1");
MenuItem mu1_mi2("Display2");
MenuItem mu1_mi3("Display3");
Menu mu2("Settings");
MenuItem mu2_mi1("Settings1");
MenuItem mu2_mi2("Settings2");
MenuItem mu2_mi3("Settings3");

// Объявления переменных и констант
const int buttonPin = 0;   // аналоговый вход для кнопок

int buttonValue = 0;   // переменная для значения АЦП кнопки
int UpButtonState = 0;     // переменная для кнопки вверх
int DownButtonState = 0;   // переменная для кнопки вниз
int SelectButtonState = 0; // переменная для кнопки выбора
int BackButtonState = 0;   // переменная для кнопки возврата

bool bRanCallback = false;
bool bForward = true;

int line = 30;             // переменная для установки настроек в линию


// Функция меню обратного вызова
// В этом примере все пункты меню можно использовать для обратного вызова.

void on_display1_selected(MenuItem* p_menu_item)
{
  Serial.println("DISPLAY1 Selected");
  display.setCursor(0,55);
  display.print("DISPLAY1 Selected");
  bRanCallback = true;
  bForward = true;
}
void on_display2_selected(MenuItem* p_menu_item)
{
  Serial.println("DISPLAY2 Selected");
  display.setCursor(0,55);
  display.print("DISPLAY2 Selected");
  //bRanCallback = false;
  bForward = true;
}
void on_display3_selected(MenuItem* p_menu_item)
{
  Serial.println("DISPLAY3 Selected");
  display.setCursor(0,55);
  display.print("DISPLAY3 Selected");
  bRanCallback = false;
  bForward = true;
}

void on_settings1_selected(MenuItem* p_menu_item)
{
  Serial.println("SETTINGS1 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS1 Selected");
  bRanCallback = true;
  bForward = true;
}
void on_settings2_selected(MenuItem* p_menu_item)
{
  Serial.println("SETTINGS2 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS2 Selected");
  bRanCallback = false;
  bForward = true;
}
void on_settings3_selected(MenuItem* p_menu_item)
{
  Serial.println("SETTINGS3 Selected");
  display.setCursor(0,55);
  display.print("SETTINGS3 Selected");
  //bRanCallback = false;
  bForward = true;
}

// Standard arduino functions

void setup()
{
  Serial.begin(9600);
  
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC);
  
  
  display.display(); 		// show splashscreen
  delay(1000);
  display.clearDisplay();   // clears the screen and buffer
  
// Menu setup
  mm.add_menu(&mu1);
  mu1.add_item(&mu1_mi1, &on_display1_selected);
  mu1.add_item(&mu1_mi2, &on_display2_selected);
  mu1.add_item(&mu1_mi3, &on_display3_selected);
  mm.add_menu(&mu2);
  mu2.add_item(&mu2_mi1, &on_settings1_selected);
  mu2.add_item(&mu2_mi2, &on_settings2_selected);
  mu2.add_item(&mu2_mi3, &on_settings3_selected);
  ms.set_root_menu(&mm);
}

void loop()
{
  buttonValue = analogRead(buttonPin);
  Serial.println(buttonValue);
  
//OLED set up
  display.display(); 		
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  line=15; //line variable reset
  //Serial.println("");
  
  
// Display Title

  display.setCursor(10,0);
  display.println("MENU CONFIGURATION");
  display.setCursor(0,5);
  display.print("_____________________");
  display.setCursor(110,15);
 
// Display the menu
  Menu const* cp_menu = ms.get_current_menu();
  MenuComponent const* cp_menu_sel = cp_menu->get_selected();
  for (int i = 0; i < cp_menu->get_num_menu_components(); ++i)
  {
    MenuComponent const* cp_m_comp = cp_menu->get_menu_component(i);
    //Serial.println(cp_m_comp->get_name());
    display.setCursor(10,line);
    display.print(cp_m_comp->get_name());
    
    if (cp_menu_sel == cp_m_comp){
      //Serial.print("<<< ");
      display.setCursor(0,line);
      display.write(16);
    }
    line=line+10;
    //Serial.println("");
  } 
 
// read the state of the pushbutton value:
  UpButtonState = buttonValue;
  if (UpButtonState > 830 && UpButtonState < 840) {    
    ms.prev(); 
  } 
  
  DownButtonState = buttonValue;
  if (UpButtonState > 860 && UpButtonState < 870) {   
    ms.next();  
  } 

  SelectButtonState = buttonValue;
  if (UpButtonState > 480 && UpButtonState < 490) {   
    ms.select();  
  } 
  
  BackButtonState = buttonValue;
  if (UpButtonState > 319 && UpButtonState < 325) {   
    ms.back();  
  } 
 
  
// Wait for two seconds so the output is viewable
  delay(200);
}

IMG_20150313_110118.jpg
 
Hi,
Is there any explanation about how the menu works ? especially about
bRanCallback = false;
bForward = true;

I wonder if I can jump to a menu from inside a running program, ie GPS to access the setup ? how would that work ?
 
Status
Not open for further replies.
Back
Top