From an OO perspective, a button is an objet user can understand - so it makes sense to create a class for it. a button can report its sate individually.
What you propose is to create a class for a group of pins to which buttons are attached so that you can group the polling into the class and you return only one button even if multiple were pressed at the same time.
From an OO perspective I don't see it.... it's not an object I have in mind.
From a programing perspective, you also check all the buttons at once, even if you don't need to update some buttons which is not needed in some cases (Say you have a mobile on a rail, when you move forward you want to only check the limit switch that is at the end of the rail and if you move backward, you only want to check the one that is at the start).
If you really want one function to poll buttons and not have a loop in your main code (hide the loop that goes through all the buttons inside the class), a typical trick to not have dynamic allocation of a container is to organize a linked list of instances as you create them and have a class function that goes through the link list
here is an example
class Car {
public:
Car(const char* n) : name(n), next(head) { head = this; }
static void printAll() {
for (const Car* c = head; c != nullptr; c = c->next) Serial.println(c->name);
}
private:
const char* name;
Car* next;
static Car* head;
};
Car* Car::head = nullptr;
Car myCars[] = { "Ferrari", "Porsche", "Rolls-Royce" };
void setup() {
Serial.begin(115200);
Car::printAll();
}
void loop() {}
You would need to define a bit more the exact behavior you want to see (describe the ramp) and is there a cap to the "acceleration" ?
The âaccelerationâ rate is subjective and difficult for me to describe.
Itâs better to describe the end goal: to rapidly traverse a count of (absolute worst case) half a million counts in a reasonably short amount of time (thirty seconds or so would be good; sixty seconds would still be acceptable) yet be able to stop the rapidly changing count at or near the desired value. The user might overshoot the target, thatâs ok because we can go up or down, and it wraps through zero. For example if you have an existing count of 800,000 and you want to set it to 80,000 you would go up. Then, press and hold the appropriate button again to get a little closer, repeat as required.
So there is a rate cap, and itâs chosen to be appropriate for the count range (zero to a million or so). I imposed a reasonable limit â see my âlimit max deltaâ comment in the code.
Think about setting a digital clock, except theyâre easier since they only have a âcountâ value of so many minutes in a day.
It would also be perfectly ok to implement an âaccelâ function that changes the ones digit at a fixed rate, followed by changing the tens digit at the same rate, followed by changing the hundreds digit at the same rate, and so forth. The less significant digits can even be blanked or have dashes to indicate theyâre not important when the user wants to change the count a few thousand at a time.
Having said all that⌠@ec2021 âs âaccelâ algorithm as adapted in the Wokwi simulation in post #38 above is nearly perfect. Load it and it illustrates what I want better than I just described it.
Oh and one more thing that I mentioned only once before â neither one of those buttons (inputs) represents the actual mechanical counter input. That will be a separate input, which ought to be trivial to add even for me
it handles buttons. I don't see a benefit for handling buttons individually. after a 5 buttons, it's more efficient to handle them as a matrix. would you prefer to have different interface to handle buttons in a matrix and not in a matrix.
Certainly if the matrix was implement as a Row / Column scan kind of thing where you drive the rows with a GPIO output and read the columns with a GPIO input (or vice versa).
A keypad / button matrix is different than a momentary button both from a user or wiring perspective. You commonly find the keypad class for a matrix and a there are countless button libraries.
If you want to deal with a collection of something in an OO way, you use containers generally.
It depends on your code and what buttons are for. If handling the press or release events for each of them is always relevant, a class function like I showed can do that without having to maintain a specifically allocated dynamic container . At the end of the day you have somewhere a loop going through the pins.
I think it's more fine grain than this question. There are no obligations as long as the intent is clear to the software programmer.
A keypad is not a button, it's multiple buttons wired in a specific way. So they appear differently to the person building the hardware. You wire a 16 button keypad in a different way than you would wire 16 individual buttons or 16 buttons with a resistor ladder.
You could choose to see those as a group of buttons and create a generic class that will adjust to the layout and offer a uniform interface to handle the events on the buttons. That's possible indeed but the programmer will have to provide in some way the type of layout upon definition of the group.
a 4x4 matrix will need 8 pins in the constructor and you'll distinguish rows and columns.
16 individual buttons will require 16 pins in the constructor
16 buttons on a resistor ladder will require only one pin but with ADC capabilities
â the programmer has to be aware of what's physically attached to the Hardware.
The code for handling detection will then be different for each case, even if the class presents a uniform API.
So I think from a developper perspective it feels simpler to have 3 classes that are specialized for the hardware you have. That's why you see a Keypad library and a button library etc.... The API can also be tailored to common usage. You might want to offer double click or triple click on a single button API whereas it's not so common to see that use case on a keypad.
you seem to be arguing right/wrong, matrix vs buttons vs button.
no. you missed my earlier point. 16 individually located buttons requires just 8 pins. they don't need to be arranged in a matrix. A row/col matrix is a method for handling many buttons. It's not necessarily a grid
16 individually located buttons requires just 8 pins if they are wired as a matrix, even if physically they are not arranged as a matrix. You'll need diodes if you want to safely detect multiple buttons being held down at the same time etc...
You could decide to wire 16 individually located buttons with 16 pins (each their own INPUT_PULLUP pin) and be done with it.
Or as I said you could decide to use a resistor ladder and have only 1 analog pin to read the state given a good ADC/
â it's a hardware design decision, the programmer will need to adjust to what has been done.
your discussion of use of diodes and resistors is irrelavent.
guess you strongly believe hardware implementaion dictates the class functions (not implementation) ... again right/wrong instead of different approach
it is somewhat - I'm just trying to express that there is a given hardware situation with a fixed wiring that the software programmer needs to know about.
â You can't write a generic class that will adjust automagically to whatever is connected.
â You can't write a generic API that can reliably notify of simultaneous multiple button press in the matrix case unless you have diodes.
The point I'm trying to make is that wether you have one generic class that adjusts to all the possible layouts and capabilities or 3 dedicated classes is a software development decision but the programer will have to provide the details of the wiring in any case. If you have 3 Classes, the developer specifies the type of wiring by picking the right class (keypad, button, resistance ladder), if you have a generic class, that class will need a way to express which type of layout is used.
The decision to write a single class or multiple class is a coding decision, both probably have merit. I'm saying that I see more merit into 3 distinct classes than one class.
I'm saying that given what is in my drawers and I see out there in projects, a Keypad class, a Button Class and a ButtonLadder (or whatever name) class make a lot of sense to me. When coding for a project, I pick the class that matches the hardware.
I've yet to come across a unified class with a meaningful API that would cover all those cases (if this is what you mean by a Buttons (with an s) class. I don't know of any and I don't feel inclined to develop one as I don't see its merit against the 3 class approach.
Even if you want a single class to handle an arbitrary number of buttons like @gcjr's code, there's no need to use dynamic allocation. Since the number of buttons is known at compile time, a templated class would be the way to go.
Donât want to get in the middle of your gentlemanly discussion but it is helping me appreciate the valid points youâre bringing up.
I did not originally discuss the addition of the âprox switchâ I added in the latest Wokwi (see above) but the value of a button class is becoming apparent. As the code evolves, there will be the need to add a specific function when it transitions from one state to another. Thatâs in addition to the obvious requirement of incrementing the count value (as opposed to presetting a starting value).
That code hasnât been implemented yet, but if I understand you correctly, the button class will simplify that addition. Itâs just another button to add to the class. Is my understanding correct?