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

tcMenu Arduinio library » Using second encoder for changing menus

Author: pruttelherrie
13/07/2022 18:21:48
Hi Dave,

On the description page of the encoders/switches plugin there's a code snippet that shows how to use a second encoder to change a certain menu item directly.

I'm wondering if it's easily doable to make it so that the 2nd encoder changes the value of the item "under the cursor", without activating (clicking) that item under the cursor? I'm working on a project where there's a lot of configuring going on, with dynamically changing enums etc. Using two encoders would speed up the use of the menu tremendously, since the user wouldn't have to click the menu, edit value, click to accept, go down, click enum, modify enum, click to accept, go up again to go to the value, etc. (I'll can a video of this process if you want).

I think the code for this would become something like: (pseudo-ish code)

// somewhere globally, define the variable 
HardwareRotaryEncoder* secondEncoder;

void setuo() {

    // other stuff...
    
    setupMenu(); // Important! This must be before any usage of switches
    
    // here we assume that menuVolume was defined in your menu project as an analog item
    secondEncoder = new HardwareRotaryEncoder(pinA, pinB, [](int encoderValue) {
        activeMenuItem = ... ???
        switch(activeMenuItem) {
              "menuvolume" : increase_or_decrease_volume(); // ???
                          break;
              "menuchannel" : increase_or_decrease_channel();
                          break;
         etc....
    });
    secondEncoder->changePrecision(menuVolume.getMaximumValue(), menuVolume.getCurrentValue()); 
    switches.setEncoder(1, secondEncoder);
}


Would this be the way to go? If so, how do I find out the activeMenuItem, and where would I put the changePrecision() call? This last one should probably change whenever one turns the primary encoder, right?

Also, is there a way to get the highlighter menuitem in the middle of the (TFTeSPI) screen? I'd like to see at least two lines of menu *below* the current highlighted item, but when scrolling up the bottom one disappears off-screen.

Author: davetcc
14/07/2022 11:07:04
To get the currently active item you can use:

MenuItem* myItem = menuMgr.findCurrentActive();


There is no direct way to be informed of every change in terms of a new item becoming active. But what you could do is to take over the control of the primary encoder yourself (instead of using the plugin-provided primary encoder support), in that case, you would set the input plugin to no input required and set up everything manually referring to the guide below. Make sure the primary encoder is encoder 0. You could even look in the projectName_menu.cpp file to see what is put there by the code generator.

http://thecoderscorner.com/products/arduino-libraries/tc-menu/menumanager-and-iteration/#controlling-the-menu-items-manually

With that, you could change the precision whenever there is a new active item. Maybe it is that simple, there could well be a lot of edge cases that I can't think of, but I think you'd need to try it yourself.

Author: pruttelherrie
14/07/2022 16:22:14
Ok, clear, thanks for the pointers.

I'll see where I end up and report back!

Iwan

Author: pruttelherrie
07/08/2022 18:43:36
Ok, got it working!

Check here for a short video that might clarify why I'm trying to do this: https://www.youtube.com/watch?v=BPyFJuu6M0I

I'm using tcMenu to "patch" or "route" guitar effects, see the "built using tcMenu" subforum for some more movies where I'm doing comparable stuff.
Anyway, going through the patchcables and connecting a setup takes quite a few clicks. The second encoder saves me a lot of clicks: instead of activating a menuItem in order to change it, I can change it with the second encoder without activating. The callback figures out if the highlighted menuItem is changeable and then changes according to the value of the second encoder. At the end of the callback I'm setting the encoder to the halfway value so I have the same starting point. Clunky but it works :

setupMenu();

    // code voor de 2e encoder
    secondEncoder = new HardwareRotaryEncoder(PB8, PB9, [](int encoderValue) {

        // do the action on the switch press
        Serial.print("2nd encoder value change: ");
        Serial.println(encoderValue);
        // uitzoeken welk menupunt actief is
        MenuItem* activeItem = menuMgr.findCurrentActive();
        switch(activeItem->getId()) {
            case 4: // menuCable, see STM32F401_eSPI_menu.cpp 
                if(encoderValue > 5) {
                    menuCable.setCurrentValue(menuCable.getCurrentValue() + 1);
                } else {
                    menuCable.setCurrentValue(menuCable.getCurrentValue() - 1);
                }
                break;
            case 5: // menuFrom
                if(encoderValue > 5) {
                    menuFrom.setCurrentValue(menuFrom.getCurrentValue() + 1);
                } else {
                    menuFrom.setCurrentValue(menuFrom.getCurrentValue() - 1);
                }
                break;
            case 6: // menuTo
                if(encoderValue > 5) {
                    menuTo.setCurrentValue(menuTo.getCurrentValue() + 1);
                } else {
                    menuTo.setCurrentValue(menuTo.getCurrentValue() - 1);    
                }
                break;
            default:  // niets gedefinieerd, doe niets.
                break;
        }
        // value van encoder 2 weer terugzetten naar midden value
        secondEncoder->setCurrentReading(5);
    });
    secondEncoder->changePrecision(10, 5); // max value, current value
    switches.setEncoder(1, secondEncoder);




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