Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Push button support for Multiplexed encoders #31

Open
Cinezaster opened this issue Feb 8, 2023 · 17 comments
Open

Push button support for Multiplexed encoders #31

Cinezaster opened this issue Feb 8, 2023 · 17 comments

Comments

@Cinezaster
Copy link

Am I correct to assume their is no push button support for Multiplexed encoders?
Is it in the pipeline?

@luni64
Copy link
Owner

luni64 commented Feb 9, 2023

Actually there is support for push buttons. See e.g. (line 15):

template <typename counter_t>
class EncPlex74165_tpl : public EncPlexBase<counter_t>
{
public:
inline EncPlex74165_tpl(unsigned nrOfEncoders, unsigned pinLD, unsigned pinCLK, unsigned pinA, unsigned pinB, unsigned pinBtn = -1);
inline ~EncPlex74165_tpl();
inline void begin(CountMode mode = CountMode::quarter);
inline void tick(); // call as often as possible
protected:
HAL::pinRegInfo_t A, B, Btn, LD, CLK;
};

Which mulitplexing scheme are you aiming for?

@Cinezaster
Copy link
Author

I'm using the 4051, I did not look into the other multiplexer codes.
https://github.com/luni64/EncoderTool/blob/master/src/Multiplexed/EncPlex4051.h
I might implement it myself.
My project has way more IO's to deal with so, I'm not sure if I'm going to keep your awesome library. In any case thx for your project and your quick response.

@luni64
Copy link
Owner

luni64 commented Feb 9, 2023

In case you add the push button (which should be simple) to the 4051 example I'd be happy to update it.

I'm not sure if I'm going to keep your awesome library

Thanks! Let me know if you need any help or "decission support" :-)

@hakonbraga
Copy link

Hi, I can see that the schematics for the 74165 mux has a extra chip for the push buttons,
but in the example code you don't use the buttons.
Could you add that to the example or tell me what is the best way to implement it like in the schematics?

@serlecu
Copy link

serlecu commented Oct 6, 2023

Looking inside src, it looks like you only need to add an extra argument to the EncPlex74165 :

https://github.com/luni64/EncoderTool/blob/master/src/Multiplexed/EncPlex74165.h

inline EncPlex74165_tpl(unsigned nrOfEncoders, unsigned pinLD, unsigned pinCLK, unsigned pinA, unsigned pinB, unsigned pinBtn = -1);

So you give the QH pin of the third encoder (pushButtons) aspinBtn argument value.

Then you could use set the callbacks with attachButtonCallback(encBtnCallback_t) as it appears in EncoderBase.h line 35 what will return (uint_fast8_t channel, int_fast8_t state)to your callback function as it appears in EncPlexBase.h line 17

it is also supposed to be analogous to lines 41 and 41 of the 74165 Multiplexed example:

 encoders[0].attachCallback(onFirstEncoder); // standard callback
 encoders.attachCallback(onAnyEncoder);

I might guess it turns into:

encoders[0].attachButtonCallback(onFirstEncoderBtn); // standard callback
encoders.attachButtonCallback(onAnyEncoderBtn);

I'll test it soon

@serlecu
Copy link

serlecu commented Oct 6, 2023

@hakonbraga
just tested and somehow Arduino IDE cant find attachButtonCallback() for using it with the whole array of encoders, but you can still assign individual callbacks like this:

constexpr unsigned QH_A = 2;   // output pin QH of shift register A
constexpr unsigned QH_B = 3;   // output pin QH of shift register B
constexpr unsigned QH_S = 4;   // output pin QH of shift register S
constexpr unsigned pinLD = 5;  // load pin for all shift registers)
constexpr unsigned pinCLK = 6; // clock pin for all shift registers

EncPlex74165 encoders(encoderCount, pinLD, pinCLK, QH_A, QH_B, QH_S);

void onFirstEncoderBtn(int state){}
void onSecondEncoderBtn(int state){}

void setup() {
...
encoders[0].attachButtonCallback(onFirstEncoderBtn);
encoders[1].attachButtonCallback(onSecondEncoderBtn);
...
}

void loop() {
    encoders.tick();
}

@bsom
Copy link

bsom commented Dec 13, 2024

Could really use this in the 4051 portion of this library... :-)

@luni64
Copy link
Owner

luni64 commented Dec 13, 2024

I can take a look at it over the weekend—it shouldn't be too difficult. However, I’d appreciate it if you could thoroughly test it, as I don’t have much time for testing right now.

@bsom
Copy link

bsom commented Jan 14, 2025

I can certainly test it as I'm in the middle of designing a device that requires it. :-)

@luni64
Copy link
Owner

luni64 commented Jan 14, 2025

Oh, since you didn't respond I thought you are not interested anymore. I'll try to come up with a solution the next days.

@bsom
Copy link

bsom commented Jan 14, 2025

Sorry, the holidays had me away from my projects for a while. Thanks for taking a look.

@luni64
Copy link
Owner

luni64 commented Jan 15, 2025

I uploaded an experimental version to the branch "AddMultiplexedButton_4051". I currently can't test it, so I hope it works. At least it compiles :-)

Here some test code (also untested). It uses three 4051 sharing the same address pins S0..S2. Two of the chips handle the phases A/B and the third handles the buttons.

#include "EncoderTool.h"
using namespace EncoderTool;

constexpr unsigned encoderCount = 8; // number of attached encoders

constexpr unsigned S0 = 0;      // address pin 0
constexpr unsigned S1 = 1;      //...
constexpr unsigned S2 = 2;      // address pin 2
constexpr unsigned SIG_A = 3;   // output pin SIG of multiplexer phase A
constexpr unsigned SIG_B = 4;   // output pin SIG of multiplexer phase B
constexpr unsigned SIG_BTN = 5; // output pin SIG of multiplexer button
                                // breakout:  https://www.sparkfun.com/products/13906
                                // datasheet: https://www.ti.com/lit/gpn/CD74HC4051

EncPlex4051 encoders(encoderCount, S0, S1, S2, SIG_A, SIG_B, SIG_BTN);

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);
    encoders.begin();
}

unsigned t0 = 0;

void loop()
{
    encoders.tick();

    for (unsigned i = 0; i < encoderCount; i++)
    {
        if(encoders[i].valueChanged())
            Serial.printf("E%d: %d\n", i, encoders[i].getValue());
        if(encoders[i].buttonChanged())
            Serial.printf("B%d: %d\n", i, encoders[i].getButton());;
    }
}

Please let me know if it works

@bsom
Copy link

bsom commented Jan 15, 2025

You are correct, it compiles. Now I just need to figure out if it works with callbacks for buttons. :-)

@luni64
Copy link
Owner

luni64 commented Jan 15, 2025

If you want to attach different callbacks for the various buttons you can use encoders[i].attachButtonCallback. I didn't implement the combined callback for all buttons since this would require changes in the base classes which I'd rather not do without testing possibiltiy. However, you can easily achive the same effect by using lambdas.

#include "EncoderTool.h"
using namespace EncoderTool;

constexpr unsigned encoderCount = 8; // number of attached encoders

constexpr unsigned S0 = 0;      // address pin 0
constexpr unsigned S1 = 1;      //...
constexpr unsigned S2 = 2;      // address pin 2
constexpr unsigned SIG_A = 3;   // output pin SIG of multiplexer phase A
constexpr unsigned SIG_B = 4;   // output pin SIG of multiplexer phase B
constexpr unsigned SIG_BTN = 5; // output pin SIG of multiplexer button
                                // breakout:  https://www.sparkfun.com/products/13906
                                // datasheet: https://www.ti.com/lit/gpn/CD74HC4051

EncPlex4051 encoders(encoderCount, S0, S1, S2, SIG_A, SIG_B, SIG_BTN);

void callback(int encNr, int state)  // will be called for each button
{
    Serial.printf("Button: %d, State: %d", encNr, state);
}

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);
    for (unsigned i = 0; i < encoderCount; i++)
    {
        encoders[i].attachButtonCallback([i](int state) { callback(i, state); });
    }
    encoders.begin();
}

void loop()
{
    encoders.tick();
}

@bsom
Copy link

bsom commented Jan 16, 2025

Well, it compiles. So, step one is good! :-)
I'm about to test it on actual hardware. I'll check back in when that is done.
Thanks again for your quick turnaround on this.

@bsom
Copy link

bsom commented Jan 16, 2025

Just tested it on real hardware and it is working well. Didn't need to debounce the presses either, which I was concerned might be an issue.

I made an individual callback for each of eight encoder buttons and it all worked swimmingly well.

Thanks so much!!!

@luni64
Copy link
Owner

luni64 commented Jan 16, 2025

Great!
I'll wait a few days and if I don't hear anything negative from you I'll merge it into the main branch.
Thanks for testing

PS: the buttons are debounced internally (I'm using the bounce2 lib from Thomas Frederic https://github.com/thomasfredericks/Bounce2)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants