Register / Login  |  Desktop view  |  Jump to bottom of page

tcMenu Arduinio library » OLED Display u8g2

Author: Andre
15/07/2019 11:09:19
Hello,
First I like to Thank you for your great work, I like it very much!

I just let the TcMenu Generator UI do a fresh code.

In the Display_Type_Var I put : U8G2_SSD1325_NHD_128X64_F_4W_HW_SPI
So I have also to declare the SPI pins like this: U8G2_SSD1325_NHD_128X64_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 23, /* dc=*/ 22, /* reset=*/ 24);
How can I do this in the fresh code?
If I do this in the arduino_menu.h file:
#ifndef MENU_GENERATED_CODE_H
#define MENU_GENERATED_CODE_H

#include <tcMenu.h>
#include "SerialTransport.h"
#include <RemoteConnector.h>
#include "tcMenuU8g2.h"

// all define statements needed
#define TCMENU_USING_PROGMEM true
#define ENCODER_PIN_A 28
#define ENCODER_PIN_B 29
#define ENCODER_PIN_OK 30

// all variables that need exporting
extern U8G2_SSD1325_NHD_128X64_F_4W_HW_SPI gfx;  //like this?--> U8G2_SSD1325_NHD_128X64_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 23, /* dc=*/ 22, /* reset=*/ 24);
extern U8g2MenuRenderer renderer;
extern IoAbstractionRef io8574;

// all menu item forward references.
extern AnalogMenuItem menuGeneralVolume;
extern BooleanMenuItem menuMute;
extern AnalogMenuItem menuHighLevel;
extern AnalogMenuItem menuMidLevel;
extern AnalogMenuItem menuLowLevel;
extern BackMenuItem menuBackVolume;
extern SubMenuItem menuVolume;
extern const ConnectorLocalInfo applicationInfo;

// Callback functions must always include CALLBACK_FUNCTION after the return type
#define CALLBACK_FUNCTION


void setupMenu();

#endif // MENU_GENERATED_CODE_H


I got a lot of compiler errors, so that is the wrong way?

Also if I compile the fresh code, it says u8g2 is not declared.

The target Board is a Arduino DUE.

Any suggestions?

Author: davetcc
15/07/2019 13:00:06
Please can you confirm if you declared the u8g2 variable in your INO sketch file. The menu library only exports the definition.

Please take a look at the sketch in the esp8266 example shipped with TcMenu. You’ll see that this both creates the global variable and initialises the display.

With both u8g2 and AdaGfx there’s just too many combinations for us to initialise it on your behalf. Instead the library assumes the display is initialised before setupMenu is called in the sketch.

Author: Andre
15/07/2019 14:33:40
I didn´t declare the u8g2. I had a look to the esp8266 example.

Now the u8g2 is declared.

Next Problem is the IoAbstractionRef declaration. I would like to have a normal Encoder with the Pin direct to the Arduino. But in the arduino_menu.h is this "extern IoAbstractionRef io8574;".
I couldn´t find any '#define IoAbstraction.h;' is that ok?
How should i declare this with pullups and interrups?

Does I also need the 'u8g2.begin();' and ' EEPROM.begin(512);' and so on?

Arduino.ino:
#include "Arduino_menu.h"

// the width and height of the attached OLED display.
#define OLED_WIDTH 128   <<<--- is that ok?
#define OLED_HEIGHT 64   <<<---- is that ok?



U8G2_SSD1325_NHD_128X64_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 23, /* dc=*/ 22, /* reset=*/ 24);
IoAbstractionRef arduinoPins = ioUsingArduino();


void setup() {
    setupMenu();

}

void loop() {
    taskManager.runLoop();

}


void CALLBACK_FUNCTION onHighLevel(int id) {
    // TODO - your menu change code
}


void CALLBACK_FUNCTION onDisplayContrast(int id) {
    // TODO - your menu change code
}


void CALLBACK_FUNCTION onLowLevel(int id) {
    // TODO - your menu change code
}


void CALLBACK_FUNCTION onGeneralLevel(int id) {
    // TODO - your menu change code
}


void CALLBACK_FUNCTION onMidLevel(int id) {
    // TODO - your menu change code
}


void CALLBACK_FUNCTION onMute(int id) {
    // TODO - your menu change code
}


Thank you
Andre

Author: Andre
15/07/2019 16:31:47
Ok, after study all the time I got it working so far.
The Display is flickering very hard.
The menu it self looks not as nice as by default from the u8g2menu.
So I guess I've to study more on the u8g2 library.

If you have any further suggestions, I would appreciate!

My Project will be a DSP active Amp with some ICEpower modules.
For that I need controlling of digital Volume, DAC-mode selection and so on.

I´m very new to Arduino, so it is hard to understand your nice Library's!

Kind Regards
Andre

Author: davetcc
15/07/2019 17:06:34
Flickering is usually a factor of the display not being updated fast enough. I know the colour TFT units update slowly in some cases - but would have thought the display you have should have been fine. Is it flickering when there are updates or always?

In terms of display rendering. U8g2 was added very recently and we’ve tested it mainly with 1306 displays in full buffer mode. There’s not much noticeable flicker with those even when using i2c. For other displays, especially non buffered types we’ve not tried it yet.

Author: Andre
15/07/2019 18:45:22
The flickering was all the Time, now I soldered the wires directly and have no flickering anymore. Before I tested the Display with some u8g2 examples and there was no flickering, so I was confused withe the sudden flickering. Any way, now it is nearly fine.
But I would like to edit the fonts and some other cosmetics. With the u8g2 examples it is easy to edit what I want but not with the tcMenu.

Author: davetcc
18/07/2019 08:24:21
To be honest it’s very easy to change the fonts and spacing with the u8g2 driver. Unfortunately you’re just using it before the documentation is fully ready.

I’ll try and complete the docs on this soon, but you just create a display configuration variable and set it in the code generator of the designer. See the u8g2 documentation for TcMenu page

https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-plugins/u8g2-renderer-plugin/

The config struct is of type:

typedef struct ColorGfxMenuConfig<const uint8_t*> U8g2GfxMenuConfig;

And is based on the template type:

https://www.thecoderscorner.com/ref-docs/tcmenu/html/_gfx_menu_config_8h.html#struct_color_gfx_menu_config

But at the end of the day, TcMenu documentation is playing catch up at the moment. Most of what you want is there but not fully documented. Which library you use is up to you really.

Further, you can easily just modify the u8g2 render that is provided by the designer. Just set the display type to custom and then modify the renderer files as appropriate.

Author: Andre
19/07/2019 19:47:08
Hello Dave,

meanwhile I was trying to understand the tcMenu lib. But I failed. Who will be impressed, I started with arduino 3 weeks ago. So I'm wondering if you can give me a small example of how to edit the fonts and to use the 'U8g2GfxMenuConfig config;'.
From your example 'takeOverDisplay' I let the UI-Designer switch to the u8g2 Display.

Here is what I've done (so far it is working):
#include <U8x8lib.h>
#include <U8g2lib.h>
#include "takeOverDisplay_menu.h"
	//#include <EepromAbstractionWire.h>
#include <IoAbstractionWire.h>
#include <TaskManager.h>
	//#include <RemoteAuthentication.h>
	//#include <RemoteMenuItem.h>

/**
 * This TcMenu example shows how to take over the display for your own purposes from a menu item.
 * It also shows how to use the dialog facilities to locally show an information dialog and also a
 * question dialog.
 * 
 * For more detail see the README.md file
 */

// Arduino direct Pins
IoAbstractionRef arduinoPins = ioUsingArduino();

//u8g2 Display Configurieren
U8G2_SSD1325_NHD_128X64_F_4W_HW_SPI my_u8g2(U8G2_R0, /* cs=*/ 23, /* dc=*/ 22, /* reset=*/ 24);
//                     ? F=FullFrame   ? Constuckt bezieht sich nur auf die U8G2lib, nur damit wird das Display ohne Menu (takeOverdispaly) gesteuert (z.B. in myDisplayFunktion).
//							? renderer wird in ****_menu.h konfiguriert. der Konstruckt 'renderer' wird zum steuern der u8g2lib im Menu benutzt.
//extern U8g2MenuRenderer renderer;
// U8g2GfxMenuConfig config;
								
// a counter that we use in the display function when we take over the display.
int counter = 0;

// if you don't have an i2c rom uncomment the avr variant and remove the i2c one.
/*AvrEeprom eeprom; */


void setup() {
	my_u8g2.begin();					//u8g2 inizialisieren
	U8g2GfxMenuConfig config;
    Serial.begin(115200);
    
    // When the renderer times out and is about to reset to main menu, you can get a callback.
    // For example if the menu should only be displayed during configuration.
    //
    // Call BEFORE setupMenu to ensure it takes effect immediately, call AFTER setupMenu if you
    // want to start in menu mode, but then apply the reset handler from that point onwards.
	renderer.setResetIntervalTimeSeconds(60); // die ResetZeit bis zum TakeOverMenu(max 60sec), ? BaseRenderer.h
	renderer.setResetCallback([] {
        counter = 0;
        renderer.takeOverDisplay(myDisplayFunction);
    });
    serdebug("Added the reset callback");

	//prepareDisplayConfig();
	config.titleFont = u8g2_font_cupcakemetoyourleader_tr;  // ?----- that is not working 
	
    // this is put in by the menu designer and must be called (always ensure devices are setup first).
    setupMenu();

    // here we use the EEPROM to load back the last set of values.
    //menuMgr.load(eeprom);
}

//
// standard setup for all taskManager based sketches. Always call runLoop in the loop.
// Never do anything long running in here.
//
void loop() {
    taskManager.runLoop();
}
//
// When the food choice option is changed on the menu, this function is called, it takes
// the value from menuFood and renders it as text in the menuText text item.
//
void CALLBACK_FUNCTION onFoodChoice(int /*id*/) {
    // copy the enum text for the current value
    char enumStr[20];
    int enumVal = menuFood.getCurrentValue();
    menuFood.copyEnumStrToBuffer(enumStr, sizeof(enumStr), enumVal);

    Serial.print("Changed food choice to ");
    Serial.println(enumStr);
    
    // and put it into a text menu item
    menuText.setTextValue(enumStr);
}
//
// this is the function called by the renderer every 1/5 second once the display is
// taken over, we pass this function to takeOverDisplay below.
//
void myDisplayFunction(unsigned int encoderValue, bool clicked) {
    if(counter == 0) {
        switches.changeEncoderPrecision(999, 50);
		//serdebug("in myDisplayFunktion");
        my_u8g2.clearBuffer();										//Speicher lehren
        my_u8g2.setFont(u8g2_font_cupcakemetoyourleader_tr);
        my_u8g2.drawStr(15,18,"We have it!");						//String ausgeben x,y, string
		my_u8g2.setFont(u8g2_font_7x14_tf);
		my_u8g2.setCursor(13,35);
		my_u8g2.print("fast geschafft");
        my_u8g2.sendBuffer();										// den oben gefüllten Speicher ausgeben
       
    }

    // We are told when the button is pressed in by the boolean parameter.
    // When the button is clicked, we give back to the menu..
    if(clicked) {
        renderer.giveBackDisplay();
        counter = 0;
    }
    else {
		//u8g2.clearBuffer();
		my_u8g2.drawRFrame(18,44,90,14, 4);				//Ein Rechteck mit Abrundungen Zeichnen (x,y,breite,höhe,radfius)
		my_u8g2.setFont(u8g2_font_unifont_t_symbols);		//Zeichensatz wählen (unifont_symbols enthält nur zeichen
		my_u8g2.drawGlyph(53,59,0x2603);					//ein Symbol zeichnen x,y,hex-wert aus Font
		my_u8g2.setFont(u8g2_font_t0_11b_tn);				
        my_u8g2.setCursor(23,55);							//Position x,y, in Pixels
		my_u8g2.print(encoderValue);						// Str und int Ausgabe
		my_u8g2.setCursor(82,55);
		my_u8g2.print(++counter);
        my_u8g2.sendBuffer();								//den oben gefüllten Buffer ausgeben
		/*
		char buffer[5];
        // otherwise update the counter.
        my_u8g2.setCursor(4, 48);
        ltoaClrBuff(buffer, ++counter, 4, ' ', sizeof(buffer));
        my_u8g2.print(buffer);
        my_u8g2.setCursor(80, 48);
        ltoaClrBuff(buffer, encoderValue, 4, '0', sizeof(buffer));
        my_u8g2.print(buffer);
		*/
    }
}

//
// We have an option on the menu to take over the display, this function is called when that
// option is chosen.
//
void CALLBACK_FUNCTION onTakeOverDisplay(int /*id*/) {
    // in order to take over rendering onto the display we just request the display
    // at which point tcMenu will stop rendering until the display is "given back".
    // Don't forget that LiquidCrystalIO uses task manager and things can be happening
    // in the background. Always ensure all operations with the LCD occur on the rendering
    // call back.

    counter = 0;
    renderer.takeOverDisplay(myDisplayFunction);
}

const char pgmInfoHeader[] PROGMEM = "Information dialog";
const char pgmQuestionHeader[] PROGMEM = "Order Food?";

void CALLBACK_FUNCTION onInfoDlg(int /*id*/) {
    // every renderer apart from NoRenderer has a dialog, that can be used to present
    // very basic info locally onto any display. Used in situations where something
    // needs to be confirmed / printed onto the local display.
    BaseDialog* dlg = renderer.getDialog();
    if(!dlg) return;

    // first we set the buttons how we want them. BTNTYPE_NONE means no button.
    dlg->setButtons(BTNTYPE_NONE, BTNTYPE_CLOSE);

    // then we show the dialog - 2nd boolean parameter is if dialog is local only
    dlg->show(pgmInfoHeader, true);

    // and then we set the second line (buffer) - must be after show.
    dlg->copyIntoBuffer("to be set..");

    // you can set the dialog buffer at some point later, it's safe, even if it's been dismissed.
    taskManager.scheduleOnce(1000, [] {
        BaseDialog* dlg = renderer.getDialog();
        dlg->copyIntoBuffer("now it's set..");
    });
}

//
// It's also possible to know when the dialog has finished, and what button was pressed.
// This is done by passing a function like below as second parameter to show.
//
void onFinished(ButtonType btn, void* /*userData*/) {
    if(btn == BTNTYPE_ACCEPT) {
        Serial.print("Food chosen was ");
        char sz[20];
        menuFood.copyEnumStrToBuffer(sz, sizeof(sz), menuFood.getCurrentValue());
        Serial.println(sz);
    }
    else {
        Serial.println("User did not choose to proceed.");
    }
}

void CALLBACK_FUNCTION onQuestionDlg(int /*id*/) {
    // yet another dialog, to ask a question this time.
    BaseDialog* dlg = renderer.getDialog();
    
    // this time we use two buttons and provide the selected index at the end (zero based)
    dlg->setButtons(BTNTYPE_ACCEPT, BTNTYPE_CANCEL, 1);
    
    // we can optionally set some data that will be given to us in the finished call back.
    dlg->setUserData(NULL); 
    
    // now we show the dialog (also giving the finished callback)
    dlg->show(pgmQuestionHeader, true, onFinished);

    // and lastly we set the text in the buffer area (2nd line)
    char sz[20];
    menuFood.copyEnumStrToBuffer(sz, sizeof(sz), menuFood.getCurrentValue());
    dlg->copyIntoBuffer(sz);
}

//
// We have a save option on the menu to save the settings. In a real system we could instead
// look at using a power down detection circuit to do this. For more info see below link.
// https://www.thecoderscorner.com/electronics/microcontrollers/psu-control/detecting-power-loss-in-powersupply/
//
void CALLBACK_FUNCTION onSaveSettings(int /*id*/) {
   // menuMgr.save(eeprom);
}

All other files in the project are not touched (just reading them smilie).
I hat to comment out the /*AvrEeprom eeprom;*/, because the Funktion did not work with Arduino DUE. If you have any idea to solve?

Dave, you will make me very very happy if you can give me an example of how to use the conf.xxxxx parameter.

Have a nice WE
Andre

Edit*: Of course I read all off your documentation but don´t understand, sorry

Author: davetcc
19/07/2019 21:00:41
Here’s an example of how to configure the rendering.

You create a config variable and then set it up using something similar to below. The below is the default example.

Finally you pass the variable name that you create as the graphics configuration in the code generator.

/**
 * Provides a basic graphics configuration suitable for low / medium resolution displays
 * @param config usually a global variable holding the graphics configuration.
 */
void prepareBasicU8x8Config(U8g2GfxMenuConfig& config) {
	makePadding(config.titlePadding, 1, 1, 1, 1);
	makePadding(config.itemPadding, 1, 1, 1, 1);
	makePadding(config.widgetPadding, 2, 2, 0, 2);

	config.bgTitleColor = WHITE;
	config.fgTitleColor = BLACK;
	config.titleFont = u8g2_font_6x12_tf;
	config.titleBottomMargin = 1;
	config.widgetColor = BLACK;
	config.titleFontMagnification = 1;

	config.bgItemColor = BLACK;
	config.fgItemColor = WHITE;
	config.bgSelectColor = BLACK;
	config.fgSelectColor = WHITE;
	config.itemFont = u8g2_font_6x10_tf;
	config.itemFontMagnification = 1;

    config.editIcon = loResEditingIcon;
    config.activeIcon = loResActiveIcon;
    config.editIconHeight = 6;
    config.editIconWidth = 8;
}

Author: davetcc
19/07/2019 21:44:38
In terms of what to replace avr eeprom with, you’re on a ARM based board with no eeprom. You could either use the EEPROM FLASH emulation that’s available in ioabstraction or an i2c EEPROM. Take a look at the eeprom examples in IoAbstraction.

Author: Andre
19/07/2019 22:40:09
Tanks for trying to help.

But that definition I already found and is not working.

tcMenuU8g2.cpp.o: In function makePadding

Error linking for board Arduino Due (Programming Port)
GfxMenuConfig.h:36: multiple definition of prepareBasicU8x8Config(ColorGfxMenuConfig<unsigned char const*>&)
Build failed for project 'takeOverDisplay'
takeOverDisplay.cpp.o: C:\Users\Andre\Documents\Arduino\


please can you give me a complete example. Everything in your doc's I read several times, but I don't understand the way of how to do and what syntax I need.
For example, I had a look on the u8g2 wiki from olicrause. For me this was easy to understand and could start playing with the lib. As I mentioned I'm new to coding.
Please give me a change to understand.

Thanks
Andre

Author: davetcc
20/07/2019 07:01:08
I've not got the rest of the files for your project so I cannot confirm it will compile, however, this should put you on the right track.

If you still have trouble after this, you can send me a PM with your whole zipped up project attached and I'll get it to compile best I can and send it back to you.

Be very careful about how you use local variables in C. They disappear once the function exits.

#include <U8x8lib.h>
#include <U8g2lib.h>
#include "takeOverDisplay_menu.h"
  //#include <EepromAbstractionWire.h>
#include <IoAbstractionWire.h>
#include <TaskManager.h>
  //#include <RemoteAuthentication.h>
  //#include <RemoteMenuItem.h>

/**
 * This TcMenu example shows how to take over the display for your own purposes from a menu item.
 * It also shows how to use the dialog facilities to locally show an information dialog and also a
 * question dialog.
 * 
 * For more detail see the README.md file
 */

// Arduino direct Pins
IoAbstractionRef arduinoPins = ioUsingArduino();

//u8g2 Display Configurieren
U8G2_SSD1325_NHD_128X64_F_4W_HW_SPI my_u8g2(U8G2_R0, /* cs=*/ 23, /* dc=*/ 22, /* reset=*/ 24);
//                     ? F=FullFrame   ? Constuckt bezieht sich nur auf die U8G2lib, nur damit wird das Display ohne Menu (takeOverdispaly) gesteuert (z.B. in myDisplayFunktion).
//              ? renderer wird in ****_menu.h konfiguriert. der Konstruckt 'renderer' wird zum steuern der u8g2lib im Menu benutzt.
                
// a counter that we use in the display function when we take over the display.
int counter = 0;

// EEPROM storage - very useful for an amplifier, two options
// if you want to store to eeprom, just purchase an i2c AT24C128 or AT24C256 or other size EEPROM (very cheap) and reliable for saving and loading
// if it's implemented for you board, you could also use the EEPROM wrapper.
// See: https://www.thecoderscorner.com/products/arduino-libraries/io-abstraction/eeprom-impl-seamless-8-and-32-bit/
/*AvrEeprom eeprom; */

// never create a varialbe that's being passed somewhere else to keep in C locally
// unless it's allocated using new. Moved it to global.
U8g2GfxMenuConfig myConfig;

/**
 * Here you can change the colours, padding and fonts for your display.
 */
void prepareIceMenuConfiguration(U8g2GfxMenuConfig& config) {
  makePadding(config.titlePadding, 1, 1, 1, 1);
  makePadding(config.itemPadding, 1, 1, 1, 1);
  makePadding(config.widgetPadding, 2, 2, 0, 2);

  config.bgTitleColor = WHITE; 
  config.fgTitleColor = BLACK;
  config.titleFont = u8g2_font_6x12_tf;
  config.titleBottomMargin = 1;
  config.widgetColor = BLACK;
  config.titleFontMagnification = 1;

  config.bgItemColor = BLACK;
  config.fgItemColor = WHITE;
  config.bgSelectColor = BLACK;
  config.fgSelectColor = WHITE;
  config.itemFont = u8g2_font_6x10_tf;
  config.itemFontMagnification = 1;

    config.editIcon = loResEditingIcon;
    config.activeIcon = loResActiveIcon;
    config.editIconHeight = 6;
    config.editIconWidth = 8;
}

void setup() {
  my_u8g2.begin();          //u8g2 inizialisieren
    Serial.begin(115200);
    
    // When the renderer times out and is about to reset to main menu, you can get a callback.
    // For example if the menu should only be displayed during configuration.
    //
    // Call BEFORE setupMenu to ensure it takes effect immediately, call AFTER setupMenu if you
    // want to start in menu mode, but then apply the reset handler from that point onwards.
    renderer.setResetIntervalTimeSeconds(60); // die ResetZeit bis zum TakeOverMenu(max 60sec), ? BaseRenderer.h
    renderer.setResetCallback([] {
      counter = 0;
      renderer.takeOverDisplay(myDisplayFunction);
    });
    serdebug("Added the reset callback");

    prepareIceMenuConfiguration(myConfig);
    
    // this is put in by the menu designer and must be called (always ensure devices are setup first).
    setupMenu();

    // here we use the EEPROM to load back the last set of values.
    //menuMgr.load(eeprom);
}

//
// standard setup for all taskManager based sketches. Always call runLoop in the loop.
// Never do anything long running in here.
//
void loop() {
    taskManager.runLoop();
}
//
// When the food choice option is changed on the menu, this function is called, it takes
// the value from menuFood and renders it as text in the menuText text item.
//
void CALLBACK_FUNCTION onFoodChoice(int /*id*/) {
    // copy the enum text for the current value
    char enumStr[20];
    int enumVal = menuFood.getCurrentValue();
    menuFood.copyEnumStrToBuffer(enumStr, sizeof(enumStr), enumVal);

    Serial.print("Changed food choice to ");
    Serial.println(enumStr);
    
    // and put it into a text menu item
    menuText.setTextValue(enumStr);
}
//
// this is the function called by the renderer every 1/5 second once the display is
// taken over, we pass this function to takeOverDisplay below.
//
void myDisplayFunction(unsigned int encoderValue, bool clicked) {
    if(counter == 0) {
        switches.changeEncoderPrecision(999, 50);
    //serdebug("in myDisplayFunktion");
        my_u8g2.clearBuffer();                    //Speicher lehren
        my_u8g2.setFont(u8g2_font_cupcakemetoyourleader_tr);
        my_u8g2.drawStr(15,18,"We have it!");           //String ausgeben x,y, string
    my_u8g2.setFont(u8g2_font_7x14_tf);
    my_u8g2.setCursor(13,35);
    my_u8g2.print("fast geschafft");
        my_u8g2.sendBuffer();                   // den oben gefüllten Speicher ausgeben
       
    }

    // We are told when the button is pressed in by the boolean parameter.
    // When the button is clicked, we give back to the menu..
    if(clicked) {
        renderer.giveBackDisplay();
        counter = 0;
    }
    else {
    //u8g2.clearBuffer();
    my_u8g2.drawRFrame(18,44,90,14, 4);       //Ein Rechteck mit Abrundungen Zeichnen (x,y,breite,höhe,radfius)
    my_u8g2.setFont(u8g2_font_unifont_t_symbols);   //Zeichensatz wählen (unifont_symbols enthält nur zeichen
    my_u8g2.drawGlyph(53,59,0x2603);          //ein Symbol zeichnen x,y,hex-wert aus Font
    my_u8g2.setFont(u8g2_font_t0_11b_tn);       
        my_u8g2.setCursor(23,55);             //Position x,y, in Pixels
    my_u8g2.print(encoderValue);            // Str und int Ausgabe
    my_u8g2.setCursor(82,55);
    my_u8g2.print(++counter);
        my_u8g2.sendBuffer();               //den oben gefüllten Buffer ausgeben
    /*
    char buffer[5];
        // otherwise update the counter.
        my_u8g2.setCursor(4, 48);
        ltoaClrBuff(buffer, ++counter, 4, ' ', sizeof(buffer));
        my_u8g2.print(buffer);
        my_u8g2.setCursor(80, 48);
        ltoaClrBuff(buffer, encoderValue, 4, '0', sizeof(buffer));
        my_u8g2.print(buffer);
    */
    }
}

//
// We have an option on the menu to take over the display, this function is called when that
// option is chosen.
//
void CALLBACK_FUNCTION onTakeOverDisplay(int /*id*/) {
    // in order to take over rendering onto the display we just request the display
    // at which point tcMenu will stop rendering until the display is "given back".
    // Don't forget that LiquidCrystalIO uses task manager and things can be happening
    // in the background. Always ensure all operations with the LCD occur on the rendering
    // call back.

    counter = 0;
    renderer.takeOverDisplay(myDisplayFunction);
}

const char pgmInfoHeader[] PROGMEM = "Information dialog";
const char pgmQuestionHeader[] PROGMEM = "Order Food?";

void CALLBACK_FUNCTION onInfoDlg(int /*id*/) {
    // every renderer apart from NoRenderer has a dialog, that can be used to present
    // very basic info locally onto any display. Used in situations where something
    // needs to be confirmed / printed onto the local display.
    BaseDialog* dlg = renderer.getDialog();
    if(!dlg) return;

    // first we set the buttons how we want them. BTNTYPE_NONE means no button.
    dlg->setButtons(BTNTYPE_NONE, BTNTYPE_CLOSE);

    // then we show the dialog - 2nd boolean parameter is if dialog is local only
    dlg->show(pgmInfoHeader, true);

    // and then we set the second line (buffer) - must be after show.
    dlg->copyIntoBuffer("to be set..");

    // you can set the dialog buffer at some point later, it's safe, even if it's been dismissed.
    taskManager.scheduleOnce(1000, [] {
        BaseDialog* dlg = renderer.getDialog();
        dlg->copyIntoBuffer("now it's set..");
    });
}

//
// It's also possible to know when the dialog has finished, and what button was pressed.
// This is done by passing a function like below as second parameter to show.
//
void onFinished(ButtonType btn, void* /*userData*/) {
    if(btn == BTNTYPE_ACCEPT) {
        Serial.print("Food chosen was ");
        char sz[20];
        menuFood.copyEnumStrToBuffer(sz, sizeof(sz), menuFood.getCurrentValue());
        Serial.println(sz);
    }
    else {
        Serial.println("User did not choose to proceed.");
    }
}
`
void CALLBACK_FUNCTION onQuestionDlg(int /*id*/) {
    // yet another dialog, to ask a question this time.
    BaseDialog* dlg = renderer.getDialog();
    
    // this time we use two buttons and provide the selected index at the end (zero based)
    dlg->setButtons(BTNTYPE_ACCEPT, BTNTYPE_CANCEL, 1);
    
    // we can optionally set some data that will be given to us in the finished call back.
    dlg->setUserData(NULL); 
    
    // now we show the dialog (also giving the finished callback)
    dlg->show(pgmQuestionHeader, true, onFinished);

    // and lastly we set the text in the buffer area (2nd line)
    char sz[20];
    menuFood.copyEnumStrToBuffer(sz, sizeof(sz), menuFood.getCurrentValue());
    dlg->copyIntoBuffer(sz);
}

//
// We have a save option on the menu to save the settings. In a real system we could instead
// look at using a power down detection circuit to do this. For more info see below link.
// https://www.thecoderscorner.com/electronics/microcontrollers/psu-control/detecting-power-loss-in-powersupply/
//
void CALLBACK_FUNCTION onSaveSettings(int /*id*/) {
   // menuMgr.save(eeprom);
}

Author: Andre
20/07/2019 14:25:07
Hallo Dave,

Thank you for you effort.
The compiler shows no error.
If I change some Items like:
config.titleFont = u8g2_font_cupcakemetoyourleader_tr;
nothing changed in the Display.

Please can you have a look to my hole project?
Here is a link to the .rar file. If this is not working, please can you give me a Email so I can send it to you:
https://www.dropbox.com/sh/px7um57fo1b8upq/AABTJquUlBSRXlNHYgNpNxlka?dl=0
or here:
https://drive.google.com/drive/folders/1xkve8SwZHC0IMO2VYigd0SnwmbJMsskR?usp=sharing

What I do not understand is why or how it is possible to override the "config" Variables allready declared in the tcMenuU8g2.cpp.
If it will not work in the *.ino, I also can edit the tcMenuU8g2.cpp file. That I tried and works but I guess this is not the right way?

A complete other story is, is it possible, to change the behavior of the Menu. For example:
click on a EnumMenuItem -> blank screen, in the top of it, the EnumMenuItem title, below that the items to scroll throu to chose.
So there is more space for the chosen items.

Andre

Author: davetcc
20/07/2019 16:20:03
I suspect that you have not set the config variable in the code generator.

In the designer UI, select the code generator and check if the display config variable is set to the name of the configuration object declared in your sketch. This should fix the situation. That is what joins the config with the menu code.

I’m actually not near a computer at the moment but I’ll try and look at the code as soon as I can.

Author: davetcc
20/07/2019 16:24:54
Also in terms of modifying the rendering of enum items, yes the rendering class that you mentioned earlier could be modified to draw items however you see fit.

However, i would recommend getting everything working before attempting that.




Register / Login  |  Desktop view  |  Jump to top of page