neu-rah / ArduinoMenu

Arduino generic menu/interactivity system
GNU Lesser General Public License v2.1
933 stars 189 forks source link

menu and array #294

Open nik-nikolaev opened 4 years ago

nik-nikolaev commented 4 years ago

Good afternoon. I took this library as a basis and faced the problem of changing the value in an array cell. what might be the problem and how to get around it? piece of code:

uint8_t  Nomer_Modeli_na_Start;
struct Struct_Dannie_Modeli
{
  uint8_t  Nomer_Modeli;
  uint8_t  myAddrRadioEndBIT;
  uint8_t  Nomer_Kanala_Radio_Modeli;

  struct Struct_Kanal
  {
    uint8_t  nazvanie_YPR_Kanala;
    uint8_t  Machtab_L;
    uint8_t  Machtab_H;
    uint8_t  Rtim_Center;
    uint8_t  Revers;
  } Kanal[SUM_Kanalov];
} Dannie_Modeli[SUM_modeley];

SELECT(Dannie_Modeli[Nomer_Modeli_na_Start].myAddrRadioEndBIT, PIPEMenu, "PIPE", doNothing, noEvent, noStyle
       , VALUE("000", 0b00000000,doNothing, noEvent)
       , VALUE("001", 0b00000001,doNothing, noEvent)
       , VALUE("010", 0b00000010,doNothing, noEvent)
       , VALUE("011", 0b00000011,doNothing, noEvent)
       , VALUE("100", 0b00000100,doNothing, noEvent)
       , VALUE("101", 0b00000101,doNothing, noEvent)
       , VALUE("110", 0b00000110,doNothing, noEvent)
       , VALUE("111", 0b00000111,doNothing, noEvent)
      );

SELECT(Nomer_Modeli_na_Start, subMenuModel, "Model", doNothing, noEvent, noStyle
       , VALUE("1", 0, doNothing, noEvent)
       , VALUE("2", 1, doNothing, noEvent)
       , VALUE("3", 2, doNothing, noEvent)
      );

MENU(subMenuRF, "Menu model", doNothing, noEvent, wrapStyle
     , SUBMENU(PIPEMenu)
     , FIELD(Dannie_Modeli[Nomer_Modeli_na_Start].Nomer_Kanala_Radio_Modeli, "Channel", "", 1, 127, 10, 1, doNothing, noEvent, wrapStyle)
     , EXIT("<Back")
    );

MENU(mainMenu, "----MENU----", doNothing, noEvent, wrapStyle
     , SUBMENU(subMenuModel)
     , SUBMENU(subMenuRF)
    );

for some reason, only cell 0 of the dannie_modeli[0] array even if you select cell 1 in the menu when you output it turns out that only cell 0 has changed

  tft.println(Nomer_Modeli_na_Start);   
    tft.println("1  2  3");
    tft.print(Dannie_Modeli[0].myAddrRadioEndBIT);   tft.print("  ");
    tft.print(Dannie_Modeli[1].myAddrRadioEndBIT);   tft.print("  ");
    tft.println(Dannie_Modeli[2].myAddrRadioEndBIT);  
    tft.print(Dannie_Modeli[0].Nomer_Kanala_Radio_Modeli);   tft.print("  ");
    tft.print(Dannie_Modeli[1].Nomer_Kanala_Radio_Modeli);   tft.print("  ");
    tft.println(Dannie_Modeli[2].Nomer_Kanala_Radio_Modeli);  

tft.println(Dannie_Modeli[Nomer_Modeli_na_Start].myAddrRadioEndBIT);  
tft.println(Dannie_Modeli[Nomer_Modeli_na_Start].Nomer_Kanala_Radio_Modeli);  
neu-rah commented 4 years ago

Hi!

yes, we can do...

static initialization wires menu options to specific variables, the trick is to use a temporary object to be the edit target and use menu events to copy data from and to that temporary object...

Because this is a common task and because we eventually need to customize the menu drawing (and for many other cases) I've made a new plugin to ease the task along with an example of usage.

please take a look at the example: https://github.com/neu-rah/ArduinoMenu/blob/master/examples/targetSel/targetSel/targetSel.ino

this is new code, barely tested, so please provide feedback if you encounter any issue

thanks

note, related code (just for reference)

old code using a temporary to edit data
https://github.com/neu-rah/ArduinoMenu/blob/master/examples/reuse/reuse/reuse.ino

custom menu (plugins) to provide access to external custom data (file systems)
https://github.com/neu-rah/ArduinoMenu/blob/master/examples/SdFat/SdFat/SdFat.ino https://github.com/neu-rah/ArduinoMenu/blob/master/examples/SDCard/SDCard/SDCard.ino

dynamic allocation of menu data (not used on the example)
https://github.com/neu-rah/ArduinoMenu/blob/master/examples/dynamic/dynamic/dynamic.ino

allocating menu objects without macros
https://github.com/neu-rah/ArduinoMenu/blob/master/examples/noMacros/noMacros/noMacros.ino

nik-nikolaev commented 4 years ago

Thanks. I will try and report the results.

kapete23 commented 4 years ago

Hello Sir..

this example targetSel not working for LCD and encoder, can you help me make example for LCD and encoder, I need that for my project.

Thanks

neu-rah commented 4 years ago

hi @k3v1n97 have you checked that it works over the serial? if so, also pick an example that is adequate for you lcd and check if it works (config pins, etc...) having that you can transport the menu structure from this example (targetSel) and replace the menu structure on the LCD example, it should work. Be careful to not replace menu input/output definitions on the LCD example, as they are specific for the lcd.

let me know if you have any issue doing this.

kapete23 commented 4 years ago

it works over in the serial but not for LCD I2C and encoder. Program execution is not stable and restarts frequently. This is a piece of code :

/********************
Arduino generic menu system

Rui Azevedo - ruihfazevedo(@rrob@)gmail.com

output: Serial
input: Serial

user defined array menu (userMenu plugin)
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>//F. Malpartida LCD's driver
#include <menu.h>//menu macros and objects
#include <menuIO/lcdOut.h>//malpartidas lcd menu output
#include <menuIO/serialIn.h>//Serial input
#include <menuIO/encoderIn.h>//quadrature encoder driver and fake stream
#include <menuIO/keyIn.h>//keyboard driver and fake stream (for the encoder button)
#include <menuIO/chainStream.h>
#include <plugin/userMenu.h>

using namespace Menu;

//===========================================================================

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

//some values for user data record
enum SelTest {Zero=0,One,Two};
enum ChooseTest {First=1,Second=2,Third=3,Last=-1};
constexpr int dataSz=5;
constexpr int nameSz=10;

//some user data record type to be edited by the menu
struct Data {
  char name[nameSz+1]="<name>     ";
  bool valid=0;
  SelTest selTest=Zero;
  ChooseTest chooseTest=First;
  //how to copy this data, being a simple data c++ will generate this for you
  Data& operator=(Data& o){
  strcpy(name,o.name);
  valid=o.valid;
  selTest=o.selTest;
  chooseTest=o.chooseTest;
  return o;
  }
};

//THE DATA <-----------------------------------------
Data myTargets[dataSz];//our data

//a temporary to be edited
//the data type must have assignment operator
//because we will later on move data back and forth between the actual data and this temporary
//menu edit is wired to this temp. and menu events will deal with the copy-call (from/to)
Data target;

//characters allowed on name field
char* constMEM alphaNum MEMMODE=" 0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,\\|!\"#$%&/()=?~*^+-{}[]€";
char* constMEM alphaNumMask[] MEMMODE={alphaNum};

//some enumeration of values allowed on some fields
TOGGLE(target.valid,editValid,"Valid: ",doNothing,noEvent,noStyle//,doExit,enterEvent,noStyle
  ,VALUE("On",HIGH,doNothing,noEvent)
  ,VALUE("Off",LOW,doNothing,noEvent)
);

SELECT(target.selTest,selMenu,"Select",doNothing,noEvent,noStyle
  ,VALUE("Zero",Zero,doNothing,noEvent)
  ,VALUE("One",One,doNothing,noEvent)
  ,VALUE("Two",Two,doNothing,noEvent)
);

CHOOSE(target.chooseTest,chooseMenu,"Choose",doNothing,noEvent,noStyle
  ,VALUE("First",First,doNothing,noEvent)
  ,VALUE("Second",Second,doNothing,noEvent)
  ,VALUE("Third",Third,doNothing,noEvent)
  ,VALUE("Last",Last,doNothing,noEvent)
);

//a function to save the edited data record
result saveTarget(eventMask e,navNode& nav) {
  _trace(MENU_DEBUG_OUT<<"saveTarget"<<endl);
  idx_t n=nav.root->path[nav.root->level-1].sel;//get selection of previous level
  myTargets[n]=target;
  return quit;
}

//if you want to print the data record name as the title,
//then you MUST create a customized print menu to replace this default one
MENU(targetEdit,"Target edit",doNothing,noEvent,wrapStyle
  ,EDIT("Name",target.name,alphaNumMask,doNothing,noEvent,noStyle)
  ,SUBMENU(editValid)
  ,SUBMENU(selMenu)
  ,SUBMENU(chooseMenu)
  ,OP("Save",saveTarget,enterEvent)
  ,EXIT("<Back")
);

//handling the user menu selection
//this will copy the selected recotd into the temp var
result targetEvent(eventMask e,navNode& nav) {
  _trace(MENU_DEBUG_OUT<<"copy data to temp.\n");
  target=myTargets[nav.sel];
  //you can store nav.sel for future reference
  return proceed;
}

//the customized print of records
//menu system wil use this to print the list of all records
struct TargetMenu:UserMenu{
  using UserMenu::UserMenu;

  // override sz() function to have variable/custom size
  // inline idx_t sz() const override {return 0;}

  //customizing the print of user menu item (len is the availabe space)
  Used printItem(menuOut& out, int idx,int len) override {
    //just printing the string name to the menu output device
    //as an item representative
    return len?out.printText(myTargets[idx].name,len):0;
  }
};

//build the user menu object, optionally giving a sub menu
#ifdef MENU_USERAM
  //for non-AVR devices or when MENU_USERAM is defined at compiler level
  TargetMenu targetsMenu("Targets",dataSz,targetEdit,targetEvent,enterEvent);
#else
  //menu allocation compatible with AVR flash ---------------------------------
  constMEM char targetsMenuTitle[] MEMMODE="Targets";
  constMEM menuNodeShadowRaw targetsMenuInfoRaw MEMMODE={
    (callback)targetEvent,
    (systemStyles)(_menuData|_canNav),
    targetsMenuTitle,
    enterEvent,
    wrapStyle,
    dataSz,
    NULL
  };
  constMEM menuNodeShadow& targetsMenuInfo=*(menuNodeShadow*)&targetsMenuInfoRaw;
  TargetMenu targetsMenu(targetsMenuInfo,targetEdit);
#endif

MENU(mainMenu,"Main menu",doNothing,noEvent,wrapStyle
  ,OBJ(targetsMenu)//attach the array edit menu on a macri build nenu
  ,EXIT("<Back")
);

//////////////////////////////////////////////////////////////////////////////
// menu IO and root navigation control

// Encoder /////////////////////////////////////
  #define encA 2
  #define encB 3
  //this encoder has a button here
  #define encBtn 4

  encoderIn<encA,encB> encoder;//simple quad encoder driver
  #define ENC_SENSIVITY 4
  encoderInStream<encA,encB> encStream(encoder,ENC_SENSIVITY);// simple quad encoder fake Stream

  //a keyboard with only one key as the encoder button
  keyMap encBtn_map[]={{-encBtn,defaultNavCodes[enterCmd].ch}};//negative pin numbers use internal pull-up, this is on when low
  keyIn<1> encButton(encBtn_map);//1 is the number of keys

  serialIn serial(Serial);

  //input from the encoder + encoder button + serial
  menuIn* inputsList[]={&encStream,&encButton,&serial};
  chainStream<3> in(inputsList);

  #define MAX_DEPTH 2

MENU_OUTPUTS(out,MAX_DEPTH
  ,LCD_OUT(lcd,{0,0,16,2})
  ,NONE//must have 2 items at least
);

NAVROOT(nav,mainMenu,MAX_DEPTH,in,out);

//function for menu idle/timemout
result idle(menuOut &o, idleEvent e) {
  switch(e) {
    case idleStart:o.print("suspending menu!");break;
    case idling:o.print("suspended...");break;
    case idleEnd:o.print("resuming menu.");
      nav.reset();
      break;
  }
  return proceed;
}

void setup() {
  pinMode(encBtn,INPUT_PULLUP);
  Serial.begin(115200);
  while(!Serial);
  Serial.println("menu 4.x test =================");Serial.flush();
  nav.timeOut=3000;
  nav.idleTask=idle;//point a function to be used when menu is suspended
  encoder.begin();
  lcd.begin(16,2);
  nav.showTitle=false;
  lcd.setCursor(0, 0);
  lcd.print("Menu 4.x LCD");
  lcd.setCursor(0, 1);
  lcd.print("r-site.net");
}

void loop() {
  nav.poll();
  delay(100);//simulate a delay when other tasks are done
}
neu-rah commented 4 years ago

whats is your memory usage on that sketch?

and that LCD init:

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

is for a normal LCD, not and i2c

and you are using same pins for lcd and encoder, please check the i2c lcd example here https://github.com/neu-rah/ArduinoMenu/blob/master/examples/LCDs/PCF8574/PCF8574/PCF8574.ino

and check if address is 0x27 (or something else)

nik-nikolaev commented 4 years ago

Good afternoon. I studied your examples. Here's what I got (part of the code, but the main idea I think is clear):

Struct_Dannie_Modeli` Dannie_Modeli[SUM_modeley]; 
Struct_Dannie_Modeli Dannie_Modeli_Temp;

result vibor_modeli_nastroiki(){
  Dannie_Modeli_Temp=Dannie_Modeli[Nomer_Modeli_na_Start];
  return proceed;
}

SELECT(Nomer_Modeli_na_Start, subMenuModel, "Model", doNothing, noEvent, noStyle
       , VALUE("1", 0, vibor_modeli_nastroiki, enterEvent)
       , VALUE("2", 1, vibor_modeli_nastroiki, enterEvent)
       , VALUE("3", 2, vibor_modeli_nastroiki, enterEvent)
      );

SELECT(Dannie_Modeli_Temp.myAddrRadioEndBIT, PIPEMenu, "PIPE", doNothing, noEvent, noStyle
       , VALUE("000", 0b00000000,doNothing, noEvent)
       , VALUE("001", 0b00000001,doNothing, noEvent)
       , VALUE("010", 0b00000010,doNothing, noEvent)
       , VALUE("011", 0b00000011,doNothing, noEvent)
       , VALUE("100", 0b00000100,doNothing, noEvent)
       , VALUE("101", 0b00000101,doNothing, noEvent)
       , VALUE("110", 0b00000110,doNothing, noEvent)
       , VALUE("111", 0b00000111,doNothing, noEvent)
      );

result Save_modeli_nastroiki(){
  Dannie_Modeli[Nomer_Modeli_na_Start]=Dannie_Modeli_Temp;
  return quit;
}

MENU(subMenuRF, "Menu model", doNothing, noEvent, wrapStyle
     , SUBMENU(PIPEMenu)
     , FIELD(Dannie_Modeli_Temp.Nomer_Kanala_Radio_Modeli, "Channel", "", 1, 127, 10, 1, doNothing, noEvent, wrapStyle)
     , OP("<Save", Save_modeli_nastroiki, enterEvent)
     , EXIT("<Back")
    );

MENU(mainMenu, "----MENU----", doNothing, noEvent, wrapStyle
     , SUBMENU(subMenuModel)
     , SUBMENU(subMenuRF)
    ); 

when you select "Nomer_Modeli_na_Start" in saves the desired cell. thanks for the tip.

neu-rah commented 4 years ago

Hi @nik-nikolaev

yes, editing the temp. and using "<Save" to assign data to selected index.. nice! so, it is complete now or still missing functionality?

kapete23 commented 4 years ago

"whats is your memory usage on that sketch?" Progmem? I use Arduino Uno, maybe memory usage with PROGMEM. Sir, I'm sorry for my English language broken. I have tried the PCF8547 LCD I2C example, still experiencing the same problem. https://github.com/neu-rah/ArduinoMenu/blob/master/examples/LCDs/PCF8574/PCF8574/PCF8574.ino

I implemented example PCF8547 to example targetSel, it became like this:

/********************
Arduino generic menu system

Rui Azevedo - ruihfazevedo(@rrob@)gmail.com

output: Serial
input: Serial

user defined array menu (userMenu plugin)
*/

#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>
#include <menu.h>//menu macros and objects
#include <menuIO/PCF8574Out.h>//arduino I2C LCD
#include <menuIO/serialIn.h>//Serial input
#include <menuIO/encoderIn.h>//quadrature encoder driver and fake stream
#include <menuIO/keyIn.h>//keyboard driver and fake stream (for the encoder button)
#include <menuIO/chainStream.h>
#include <plugin/userMenu.h>

using namespace Menu;

//===========================================================================

LiquidCrystal_PCF8574 lcd(0x27);  // set the LCD address to 0x27 for a 16 chars and 2 line display 

//some values for user data record
enum SelTest {Zero=0,One,Two};
enum ChooseTest {First=1,Second=2,Third=3,Last=-1};
constexpr int dataSz=5;
constexpr int nameSz=10;

//some user data record type to be edited by the menu
struct Data {
  char name[nameSz+1]="<name>     ";
  bool valid=0;
  SelTest selTest=Zero;
  ChooseTest chooseTest=First;
  //how to copy this data, being a simple data c++ will generate this for you
  Data& operator=(Data& o){
  strcpy(name,o.name);
  valid=o.valid;
  selTest=o.selTest;
  chooseTest=o.chooseTest;
  return o;
  }
};

//THE DATA <-----------------------------------------
Data myTargets[dataSz];//our data

//a temporary to be edited
//the data type must have assignment operator
//because we will later on move data back and forth between the actual data and this temporary
//menu edit is wired to this temp. and menu events will deal with the copy-call (from/to)
Data target;

//characters allowed on name field
char* constMEM alphaNum MEMMODE=" 0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,\\|!\"#$%&/()=?~*^+-{}[]€";
char* constMEM alphaNumMask[] MEMMODE={alphaNum};

//some enumeration of values allowed on some fields
TOGGLE(target.valid,editValid,"Valid: ",doNothing,noEvent,noStyle//,doExit,enterEvent,noStyle
  ,VALUE("On",HIGH,doNothing,noEvent)
  ,VALUE("Off",LOW,doNothing,noEvent)
);

SELECT(target.selTest,selMenu,"Select",doNothing,noEvent,noStyle
  ,VALUE("Zero",Zero,doNothing,noEvent)
  ,VALUE("One",One,doNothing,noEvent)
  ,VALUE("Two",Two,doNothing,noEvent)
);

CHOOSE(target.chooseTest,chooseMenu,"Choose",doNothing,noEvent,noStyle
  ,VALUE("First",First,doNothing,noEvent)
  ,VALUE("Second",Second,doNothing,noEvent)
  ,VALUE("Third",Third,doNothing,noEvent)
  ,VALUE("Last",Last,doNothing,noEvent)
);

//a function to save the edited data record
result saveTarget(eventMask e,navNode& nav) {
  _trace(MENU_DEBUG_OUT<<"saveTarget"<<endl);
  idx_t n=nav.root->path[nav.root->level-1].sel;//get selection of previous level
  myTargets[n]=target;
  return quit;
}

//if you want to print the data record name as the title,
//then you MUST create a customized print menu to replace this default one
MENU(targetEdit,"Target edit",doNothing,noEvent,wrapStyle
  ,EDIT("Name",target.name,alphaNumMask,doNothing,noEvent,noStyle)
  ,SUBMENU(editValid)
  ,SUBMENU(selMenu)
  ,SUBMENU(chooseMenu)
  ,OP("Save",saveTarget,enterEvent)
  ,EXIT("<Back")
);

//handling the user menu selection
//this will copy the selected recotd into the temp var
result targetEvent(eventMask e,navNode& nav) {
  _trace(MENU_DEBUG_OUT<<"copy data to temp.\n");
  target=myTargets[nav.sel];
  //you can store nav.sel for future reference
  return proceed;
}

//the customized print of records
//menu system wil use this to print the list of all records
struct TargetMenu:UserMenu{
  using UserMenu::UserMenu;

  // override sz() function to have variable/custom size
  // inline idx_t sz() const override {return 0;}

  //customizing the print of user menu item (len is the availabe space)
  Used printItem(menuOut& out, int idx,int len) override {
    //just printing the string name to the menu output device
    //as an item representative
    return len?out.printText(myTargets[idx].name,len):0;
  }
};

//build the user menu object, optionally giving a sub menu
#ifdef MENU_USERAM
  //for non-AVR devices or when MENU_USERAM is defined at compiler level
  TargetMenu targetsMenu("Targets",dataSz,targetEdit,targetEvent,enterEvent);
#else
  //menu allocation compatible with AVR flash ---------------------------------
  constMEM char targetsMenuTitle[] MEMMODE="Targets";
  constMEM menuNodeShadowRaw targetsMenuInfoRaw MEMMODE={
    (callback)targetEvent,
    (systemStyles)(_menuData|_canNav),
    targetsMenuTitle,
    enterEvent,
    wrapStyle,
    dataSz,
    NULL
  };
  constMEM menuNodeShadow& targetsMenuInfo=*(menuNodeShadow*)&targetsMenuInfoRaw;
  TargetMenu targetsMenu(targetsMenuInfo,targetEdit);
#endif

MENU(mainMenu,"Main menu",doNothing,noEvent,wrapStyle
  ,OBJ(targetsMenu)//attach the array edit menu on a macri build nenu
  ,EXIT("<Back")
);

//////////////////////////////////////////////////////////////////////////////
// menu IO and root navigation control

// Encoder /////////////////////////////////////
  #define encA 2
  #define encB 3
  //this encoder has a button here
  #define encBtn 4

  encoderIn<encA,encB> encoder;//simple quad encoder driver
  #define ENC_SENSIVITY 4
  encoderInStream<encA,encB> encStream(encoder,ENC_SENSIVITY);// simple quad encoder fake Stream

  //a keyboard with only one key as the encoder button
  keyMap encBtn_map[]={{-encBtn,defaultNavCodes[enterCmd].ch}};//negative pin numbers use internal pull-up, this is on when low
  keyIn<1> encButton(encBtn_map);//1 is the number of keys

  serialIn serial(Serial);

  //input from the encoder + encoder button + serial
  menuIn* inputsList[]={&encStream,&encButton,&serial};
  chainStream<3> in(inputsList);

  #define MAX_DEPTH 2

MENU_OUTPUTS(out,MAX_DEPTH
  ,LCD_OUT(lcd,{0,0,16,2})
  ,NONE//must have 2 items at least
);

NAVROOT(nav,mainMenu,MAX_DEPTH,in,out);

//function for menu idle/timemout
result idle(menuOut &o, idleEvent e) {
  switch(e) {
    case idleStart:o.print("suspending menu!");break;
    case idling:o.print("suspended...");break;
    case idleEnd:o.print("resuming menu.");
      nav.reset();
      break;
  }
  return proceed;
}

void setup() {
  pinMode(encBtn,INPUT_PULLUP);
  Serial.begin(115200);
  while(!Serial);
  Serial.println("menu 4.x test =================");Serial.flush();
  nav.timeOut=3000;
  nav.idleTask=idle;//point a function to be used when menu is suspended
  encoder.begin();
  lcd.begin(16,2);
  lcd.setBacklight(255);
  nav.showTitle=false;
  lcd.setCursor(0, 0);
  lcd.print("Menu 4.x LCD");
  lcd.setCursor(0, 1);
  lcd.print("r-site.net");
}

void loop() {
  nav.poll();
  delay(100);//simulate a delay when other tasks are done
}

please try the code on your microcontroller (Arduino Uno)

I have trouble explaining the problem, in essence, the results of the program execution in the serial are different from the LCD I2C + encoder.

my I2C address is 0x27.

Thanks.

neu-rah commented 4 years ago

Hi @k3v1n97 the code above compiles for an arduino uno, can you please open an new issue for this? because we are getting off topic on the original.

there is also https://gitter.im/ArduinoMenu/Lobby

can you send pictures of serial and lcd menu?

kapete23 commented 4 years ago

Hi Sir Pictures are here, I open an new issue,

https://github.com/neu-rah/ArduinoMenu/issues/296#issue-618824569

nik-nikolaev commented 4 years ago

Hi @nik-nikolaev

yes, editing the temp. and using "<Save" to assign data to selected index.. nice! so, it is complete now or still missing functionality?

Hi @neu-rah

I understood this question, but the fact is that I have another array of structures nested in my array of structures. and there is still a lot of work to do.

neu-rah commented 4 years ago

the targetSel example uses an array as menu source and an optional submenu as edit, so that the first will provide indexing for the second... the same schema you are using but automated, maybe it helps chaining 2 user menus to obtain a double indexing.

I'm just guessing of course :D

nik-nikolaev commented 4 years ago

Yes, thank you I will use it.

sirias52 commented 2 years ago

it is possible to save the selected object in eeprom?

[1]><1>
[2] <2>
[3] <3>
[4] <Back

if you restart the arduino, the names are not saved

hicksan commented 2 years ago

Yes it is. I did it by following the examples in the standard EEPROM.h library and then setting up a action subroutine called from an OP menu item to save all required variables in one go. There is a matching read operation, also with an OP menu item. This saves on unnecessary writing to EEPROM every time a field is updated - since the memory has a finite use lifespan. The data saved includes a timestamp which updates the read and save menu prompts when these items are activated, so you know when last saved, and the date last read from.

sirias52 commented 2 years ago

in this example (https://github.com/neu-rah/ArduinoMenu/blob/master/examples/targetSel/targetSel/targetSel.ino) it is possible to save the name field?, because when restarting the arduino the name field is erased.