The ButtonToSwitch libraries projects continue their development in the following Github repositories:
For the STM32-FreeRTOS environment:
For the ESP32-RTOS Arduino environment
For the Arduino for AVR enviornment
An ESP32-RTOS Arduino library that builds switch mechanisms replacements out of simple push buttons.
By using just a push button (a.k.a. momentary switches or momentary buttons, MPB for short from here on) the classes implemented in this library will manage, calculate and update different parameters to generate the behavior of standard electromechanical switches. Those parameters include presses, releases, timings, counters or secondary input readings as needed.
The instantiated switch state is updated independently by a standard FreeRTOS software timer (or ESP-RTOS in this case), that keeps the ON/OFF state of the objects created constantly updated. The timer setup is managed by in-class methods, including the possibility to pause, resume or end the timer of each object independently of the others.
Each class offers a wide range of methods to set, read and modify every significant aspect of each switch mechanism simulated, and the signal received from the push button is debounced for a correct behavior of the event processing.
The benefits of the use of those simulated switches mechanisms are not just economic, as push buttons come in a wide range of prices and qualities similar to the simulated hardware switches.
In a domestic lighting project, for example, detecting after the implementation, through the daily use, that an installed switch was not the best choice when a physical switch is involved, requires for the correction to a best suited kind of switch a bunch of activities to get the change of the switch unit done:
- Searching for the availability of a best suited switch to match our intended functionalities.
- Getting that different best suited switch, with the time and resources investment involved.
- Uninstalling the first switch.
- Maybe modifying the cabling.
- Installing the new switch...
While with the simulated switches this situation might be solved by just changing the object class, or modifying the instantiation parameters if needed, and the switch is already changed!!
- Want to keep the timed lights-on longer? Just a parameter.
- Want to turn off the pilot light because it bothers? Another parameter.
- Want to be sure the door mechanism isn't kept unlocked with an adhesive tape? Change the switch class.
In an Industrial production machines environment the operator's physical security policies enforcement implies that no time can be wasted and the switch must fit perfectly it's purpose, while still giving the chance to change it's working parameters to adjust the mechanism to changing production operations. In this case the development depending on a simple "OK to proceed"/"The security device is correctly activated" might become a dangerous issue if not correctly isolated and solved as a remove and replace solution. The security switches must comply with issues as:
- Activation enforcement
- Release enforcement
- Time Voidable activation or releases
- Activation sequence enforcement
- Production related disabling of any of the switches while conserving the activation logic... and so many others.
Just to add possibilities, consider that everywhere the "Momentary Push Button" is mentioned, any kind of momentary activation signal provider might be used instead: touch sensors, PIR sensors, RFID signals, fingerprint reader and so on...
- Debounced Momentary Button (a.k.a. Momentary switch, a.k.a. Pushbutton)
- Debounced Delayed Momentary Button
- Toggle switch (a.k.a. alternate, a.k.a. latched)
- Timer toggled (a.k.a. timer switch)
- Hinted Timer toggled (a.k.a. staircase timer switch)
- External released toggle (a.k.a. Emergency latched)
- Time Voidable Momentary Button (a.k.a. anti-tampering switch)
(This is a subset of the classes implemented in the refactored STM32 RTOS version of this library)
The system timer will periodically check the input pins associated to the objects and compute the object's output flags, the timer period for that checking is a general parameter that can be changed. The classes provide a callback function to keep the behavior of the objects updated, a valid approach is to create a task for each object to keep status of the outputs associated with each switch updated , or to create a single task to update a number of switches, and act accordingly (turn On/ Off loads, turn On/Off warning signals or other actions). The classes implement a xTaskNotifyGive() FreeRTOS macro (a lightweight binary semaphore) to let those tasks implemented to be blocked until they receive the notification of a change, to avoid the tasks polling the objects constantly, freeing resources and processor time. For those not interested in using this mechanism all the attributes of the classes are available without involving it.
Examples are provided for each of the classes, usually as pairs in each example to show possible interactions between different objects, the possible implementations with tasks or with a refreshing mechanism in the main loop() (loopTask), or any other thread created. The object input status checking can be paused, restarted and even ended. If the object's status checking is ended the timer entry will be deleted, to release resources.
So this library implements the inner mechanisms of some switches, the hardware interface (the load connection, warning outputs, etc.) might be developed differently for every project, or the switchHIL library (https://github.com/GabyGold67/SwitchesHardwareInterfaceLayer) might be used, as it implements Hardware Interface Layers for some usual switches, and for examples of implementations for some classic solutions.
The Debounced Momentary Button keeps the ON state since the moment the signal is stable (debouncing process) and until the moment the MPB is released.
Method | Parameters |
---|---|
DbncdMPBttn | None |
DbncdMPBttn | uint8_t mpbttnPin(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett))) |
begin() | (unsigned long int pollDelayMs) |
clrStatus() | None |
end() | None |
getCurDbncTime() | None |
getIsOn() | None |
getOutputsChange() | None |
getTaskToNotify() | None |
init() | uint8_t mpbttnPin(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett))) |
pause() | None |
resetDbncTime() | None |
resume() | None |
setDbncTime() | unsigned long int newDbncTime |
setOutputsChange() | bool newOutputChange |
setTaskToNotify() | TaskHandle_t newHandle |
Default Class Constructor, creates an instance of the class. This constructor is provided as a tool to create "yet to know parameters" objects, blank objects to use in copies, pointers, etc. The init() method is provided to configure the required attributes to the objects created by this constructor, and there is no other method for setting those basic attributes.
None
The object created.
DbncdMPBttn myDButton();
Class constructor, creates an instance of the class. There's no need to configure the input pin before calling the method, as the constructor takes care of the task.
mpbttnPin: uint8_t (unsigned char), passes the pin number that is connected to the push button. The pin must be free to be used as a digital input.
pulledUp: optional boolean, indicates if the input pin must be configured as INPUT_PULLUP (true, default value), or INPUT_PULLDOWN (false), to calculate correctly the expected voltage level in the input pin. The pin is configured by the constructor so no previous programming is needed. The pin must be free to be used as a digital input, and must be a pin with a internal pull-up circuit, as not every GPIO pin has the option.
typeNO: optional boolean, indicates if the mpb is a Normally Open (NO) switch (true, default value), or Normally Closed (NC) (false), to calculate correctly the expected level of voltage indicating the mpb is pressed.
dbncTimeOrigSett: optional unsigned long integer (uLong), indicates the time (in milliseconds) to wait for a stable input signal before considering the mpb to be pressed (or not pressed). If no value is passed the constructor will assign the minimum value provided in the class, that is 50 milliseconds as it is an empirical value obtained in various published tests.
The object created.
DbncdMPBttn myDButton(21, true, true, 100);
Attaches the instantiated object to a timer that monitors the input pin and updates the object status, if the object was not already attached to a timer before. The frequency of that periodic monitoring is passed as a parameter in milliseconds, and is a value that must be small (frequent) enough to keep the object updated, but not so frequent that no other tasks can be executed. A default value is provided based on empirical values obtained in various published tests.
pollDelayMs: unsigned long integer (ulong) optional, passes the time between polls in milliseconds.
true: the object could be attached to a timer, or if it was already attached to a timer when the method was invoked.
false: the object could not create the needed timer, or the object could not be attached to it.
myDButton.begin(20);
//Attaches de object to a monitoring timer set at 20 milliseconds between checkups.
Resets some object's attributes to safely resume operations -by using the resume() method- after a pause() without risking generating false "Valid presses" and "On" situations due to dangling flags or partially ran time counters.
None
None
myDButton.clrStatus();
Detaches the object from the timer that monitors the input pin/s and updates the object status. The timer daemon entry is deleted for the object.
None
true: the object detachment procedure and timer entry removal was successful.
false: the object detachment and/or entry removal was rejected by the O.S..
myDButton.end();
Returns the current value used for the debouncing process in milliseconds. The original value for the debouncing process used at instantiation time might be changed with the setDbncTime() or with the resetDbncTime() methods, so this method is provided to get the current value in use.
None
unsigned long integer: The current debounce time, in milliseconds, being used in the debounce process of the current object.
myDButton.getCurDbncTime();
Returns the current value of the isOn flag, either true (On) or false (Off). This flag alone might be considered the "Raison d'etre" of all this classes design: the isOn signal is not just the detection of an expected voltage value at a mcu pin, but the combination of that voltage, filtered and verified, for a determined period of time and until a new event modifies that situation.
None
true: the implemented switch is in On state.
false: the implemented switch is in Off state.
bool lightStatus = myDButton.getIsOn();
Returns the current value of the flag indicating if there have been changes in the output flag/s since last flag resetting. The flag only signals changes have been done, nor which flags nor how many times changes have taken place.
None
true: there have been output flag changes in the object.
false: there have been no output flag changes in the object.
bool outputStatus = myDButton.getOutputsChange();
Returns the current TaskHandle for the task to be notified by the object when its output flags changes (indicating there have been changes in the outputs since last FreeRTOS notification). When the object is created, this value is set to nullptr and a valid TaskHandle_t value might be set by using the setTaskToNotify() method. The task notifying mechanism will not be used while the task handle keeps the nullptr value, in which case the solution implementation will have to include a mechanism to test the object status, ideally through getOutputsChange() first, and in the case of a true returned from it a getIsOn() and the other methods corresponding to the other flags returned by the object.
None
TaskHandle_t value pointing to the task implemented to be notified of the change of values of the flags of the objet if it was set to some value not equal to nullptr, or nullptr otherwise.
TaskHandle_t taskNotified = myDButton.getTaskToNotify();
Sets the significant attributes that are needed at instantiation time, and makes the needed operations to get the internal mechanisms active. This method can be applied to objects instantiated with de default constructor only. Having the mpbttnPin attribute already set to a valid value blocks the init() method of being executed.
mpbttnPin: Analog to the DbncdMPBttn constructor equally named parameter.
pulledUp: optional boolean, analog to the DbncdMPBttn constructor equally named parameter.
typeNO: analog to the DbncdMPBttn constructor equally named parameter.
dbncTimeOrigSett: analog to the DbncdMPBttn constructor equally named parameter.
The object with the corresponding attributes set to their initial values.
myDButton.init(21, true, true, 100);
Stops the software timer updating the calculation of the object internal flags. The timer will be kept for future use, but the flags will keep their last values and will not be updated until the timer is restarted with the .resume()
method.
None
true: the object's timer could be stopped by the O.S..
false: the object's timer couldn't be stopped by the O.S..
myDButton.pause();
Resets the debounce time of the object to the value used at instantiation. In case the value was not specified at instantiation the default debounce time value will be used. As the time used at instantiation might be changed with the setDbncTime(), this method reverts the value.
None
true: the value could be reverted.
false: the value couldn't be reverted due to unexpected situations.
myDButton.resetDbncTime();
Restarts the software timer updating the calculation of the object internal flags. The timer will stop its function of computing the flags values after calling the .pause()
method and will not be updated until the timer is restarted with this method.
None
true: the object's timer could be restarted by the O.S..
false: the object's timer couldn't be restarted by the O.S..
myDButton.resume();
Sets a new time for the debouncing period. The value must be equal or greater than the minimum empirical value set as a property for all the classes, 20 milliseconds. A long debounce time will produce a delay in the press event generation, making it less "responsive".
newDbncTime: unsigned long integer, the new debounce value for the object.
true: the new value is in the accepted range and the change was made.
false: the value was already in use, or was out of the accepted range, no change was made.
myDButton.setDbncTime(200);
//Sets the new debounce time and returns true.
myDButton.setDbncTime(15);
//Returns false and the debounce time is kept unchanged.
Sets the value of the flag indicating if a change took place in any of the output flags (IsOn included). The usual path for the _outputsChange flag is to be set to true by any method changing an output flag, the callback function signaled to take care of the hardware actions because of this changes clears back _outputsChange after taking care of them. In the unusual case the developer wants to "intercept" this sequence, this method is provided to set (true) or clear (false) _outputsChange value.
newOutputChange: boolean, the new value to set the _outputsChange flag to.
true: The value change was successful.
false: The value held by _outputsChange and the newOutputChange parameter are the same, no change was then produced.
myDButton.setOutputsChange(false);
//Returns true if the newOutputChange if different to the _outputsChange value, and the change is made.
Sets the pointer to the task to be notified by the object when its output flags changes (indicating there have been changes in the outputs since last FreeRTOS notification). When the object is created, this value is set to nullptr and a valid TaskHandle_t value might be set by using this method. The task notifying mechanism will not be used while the task handle keeps the nullptr value. After the TaskHandle value is set it might be changed to point to other task
newHandle: TaskHandle_t, a valid handle of an actual existent task/thread running. There's no provided exception mechanism for dangling pointer errors caused by a pointed task being deleted and/or stopped.
true: A TaskHandle_t type was passed to the object to be it's new pointer to the task to be messaged when a change in the output flags occur. There's no checking for the validity of the pointer, if it refers to an active task/thread whatsoever.
false: The value passed to the method was nullptr, and that's the value will be stored, so the whole RTOS messaging mechanism won't be used.
TaskHandle_t myHwUpdtTask;
[...]
myDButton.setTasToNotify(myHwUpdtTask);
The Debounced Delayed Momentary Button, keeps the ON state since the moment the signal is stable (debouncing process), plus a delay added, and until the moment the push button is released. The reasons to add the delay are design related and are usually used to avoid unintentional presses, or to give some equipment (load) that needs time between repeated activations the benefit of the pause. If the push button is released before the delay configured, no press is registered at all. The delay time in this class as in the other that implement it, might be zero (0), defined by the developer and/or modified in runtime.
Method | Parameters |
---|---|
DbncdDlydMPBttn | None |
DbncdDlydMPBttn | uint8_t mpbttnPin(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett(, unsigned long int strtDelay)))) |
getStrtDelay() | None |
init | uint8_t mpbttnPin(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett(, unsigned long int strtDelay)))) |
setStrtDelay() | (unsigned long int newStrtDelay) |
DbncdDlydMPBttn(uint8_t mpbttnPin, bool pulledUp, bool typeNO, unsigned long int dbncTimeOrigSett, unsigned long int strtDelay)
Class constructor, creates an instance of the class for each Debounced Delayed Momentary Push Button. There's no need to configure the input pin before calling the method, as the constructor takes care of the task.
mpbttnPin: uint8_t (unsigned char), passes the pin number that is connected to the push button. The pin must be free to be used as a digital input.
pulledUp: optional boolean, indicates if the input pin must be configured as INPUT_PULLUP (true, default value), or INPUT_PULLDOWN(false), to calculate correctly the expected voltage level in the input pin. The pin is configured by the constructor so no previous programming is needed. The pin must be free to be used as a digital input.
typeNO: optional boolean, indicates if the mpb is a Normally Open switch (true, default value), or Normally Closed (false), to calculate correctly the expected level of voltage indicating the mpb is pressed.
dbncTimeOrigSett: optional unsigned long integer (uLong), indicates the time (in milliseconds) to wait for a stable input signal before considering the mpb to be pressed. If no value is passed the constructor will assign the minimum value provided in the class, that is 50 milliseconds as it is a empirical value obtained in various published tests.
strtDelay: optional unsigned long integer (uLong), indicates the time (in milliseconds) to wait after the debouncing is completed and before rising the ON flag. If no value is passed the constructor will assign 0 milliseconds, and the resulting behavior will be the same as implementing a DbncdMPBttn. If the mpb is released before completing the strtDelay time, no ON signal will be produced.
The object created.
DbncdMPBttn myDDButton(21, true, true, 100, 500);
Returns the current value of time used by the object to rise the isOn flag, after the debouncing process ends, in milliseconds. If the MPB is released before completing the debounce and the delay time, no press will be detected by the object, and the isOn flag will not be rised. The original value for the delay process used at instantiation time might be changed with the setStrtDelay() method, so this method is provided to get the current value in use.
None
unsigned long integer: The current delay time, in milliseconds, being used before rising the isOn flag, after the debounce process of the current object.
unsigned long curDelay {myDButton.getStrtDelay()};
//Stores the current Start delay value in the curDelay variable
Sets a new time for the Start Delay period. The value must be equal or greater than 0 milliseconds, in the case of equal to 0 the instantiated object will act as a DbncdMPBttn class object. A long Start Delay time will produce a long delay in the press event generation, making it less "responsive".
newStrtDelay: unsigned long integer, the new start delay value for the object.
true: the new value is different than the previously set value, so the change was made.
false: the value passed is equal to the one already in use, no change was made.
myDButton.setStrtDelay(0);
//Sets the new debounce time to 0, there will no time added to the debounce process, the MPB will act as a DbncdMPBttn.
myDButton.setStrtDelay(myDButton.getStrtDelay() + 15);
//Changes the current start delay time by adding 15 milliseconds, and returns true.
The Toggle switch keeps the ON state since the moment the signal is stable (debouncing + Delay process), and keeps the ON state after the push button is released and until it is pressed once again. So this simulates a simple On-Off switch like the ones used to turn on/off a room light. One of the best things about the software simulated switch is that any amount of switches might be set up in a parallel configuration, so that an unlimited number of entrances or easy accessible points can each have a switch to turn on/off the same resource.
Method | Parameters |
---|---|
LtchMPBttn | uint8_t mpbttnPin(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett(, unsigned long int strtDelay)))) |
getUnlatchPend() | None |
setUnlatchPend() | None |
LtchdMPBttn(uint8_t mpbttnPin, bool pulledUp, bool typeNO, unsigned long int dbncTimeOrigSett, unsigned long int strtDelay)
Class constructor, creates an instance of the class for each Latched Momentary Push Button. There's no need to configure the input pin before calling the method, as the constructor takes care of the task.
Same as DbncdDlydMPBttn() class objects constructor.
Returns the current value of unlatch pending flag, whose boolean value indicates if the conditions were given to unlatch a LtchMPBttn object. The periodical timer event that takes care of keeping the internal and external objects' flags updated takes care of the actions required to set the flag and eventually acting on this flag value. This method makes it possible to know the flag value to give the developer a tool to generate other events his development might require, but not by modifying the class.
None
true: The current object's unlatchPending flag is set.
false: The current object's unlatchPending flag is reset.
if(myDButton.getUnlatchPend()){...}
//Executes some code if the unlatchPending flag is set.
Sets to true the value of the internal flag unlatchPending. It is the equivalent to physically executing the action that releases the latch that keeps the isOn signal lactched, in this case it will be the equivalent to pressing the MPB while the isOn signal is true. This method gives an alternative to generate the appropiate signal to unlatch the LtchMPBttn.
None
true: the unlatchPending value was set.
false: Abnormal situation, the unlatchPending flag could not be set.
myDButton.setUnlatchPend();
The Timer toggled or Timer Switch, keeps the ON state since the moment the signal is debounced and delayed, and keeps the ON state during a set time. The switch time is set at instantiation, and can be modified through the provided methods. The switch implementation gives the option to allow to reset the timer before reaches the time limit if the push button is pressed again.
Method | Parameters |
---|---|
TmLtchMPBttn | uint8_t mpbttnPin, unsigned long int actTime(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett(, unsigned long int strtDelay)))) |
getSvcTime() | None |
setSvcTime() | unsigned long int newSvcTime |
setTmerRstbl() | bool isRstbl |
TmLtchdMPBttn(uint8_t mpbttnPin, unsigned long int svcTime, bool pulledUp, bool typeNO, unsigned long int dbncTimeOrigSett, unsigned long int strtDelay)
Class constructor, creates an instance of the class for each Time Latched Momentary Push Button. There's no need to configure the input pin before calling the method, as the constructor takes care of the task.
svcTime: unsigned long integer (uLong), indicates the time (in milliseconds) the ON flag will be kept set (true) after the debounce & delay process ends. The value must be greater or equal to the _MinSrvcTime library constant. The constant is set to give a minimum margin to keep the processes times guaranteed for a manual pushbutton implementation. There is no set upper limit for this parameter besides that imposed by the data type.
Rest of the parameters are as described at LtchdMPBttn() class objects constructor.
Returns the current value of time used by the object to keep the isOn flag rised, after the debouncing & delaying process ends, in milliseconds. The original value for the service time used at instantiation might be changed with the setSvcTime() method, so this method is provided to get the current value in use.
None
unsigned long integer: The current service time, in milliseconds, being used to keep rised the isOn flag, after the debounce & delay process of the current object.
unsigned long curOnTime {myDButton.getSvcTime()};
//Stores the current Start delay value in the curDelay variable
Sets a new time for the Service Time period. The value must be greater or equal to the _MinSrvcTime library constant.
newSvcTime: unsigned long integer, the new service time value for the object.
true: the new value is valid and different than the previously set value, so the change was made.
false: the value passed is equal to the one already in use, or is no greater or equal to the _MinSrvcTime value, so no change was made.
myDButton.setSvcTime(0);
// Fails as it's not a valid value.
myDButton.setSvcTime(myDButton.getSvcTime() + 15);
//Changes the current service time by adding 15 milliseconds, and returns true.
The Hinted Timer toggled, or Staircase Timer Switch, keeps the ON state since the moment the signal is debounced, and keeps the state during a set time, the switch time is set at instantiation, and can be modified through the provided methods. The switch implementation gives the option to allow to reset the timer before it gets to the end if the push button is pressed, the option to give a warning when the time is close to the end through a second flag (remaining time is defined as a percentage of the total ON time and it's configurable), and the possibility to set a third signal ON while the switch is off, just like the pilot light (hint) in a staircase timer switch. The warning signal is independent of the off hint.
Method | Parameters |
---|---|
HntdTmLtchMPBttn | uint8_t mpbttnPin, unsigned long int actTime(, unsigned int wrnngPrctg(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett(, unsigned long int strtDelay))))) |
getPilotOn() | None |
getWrnngOn() | None |
setKeepPilot() | bool keepPilot |
updPilotOn() | None |
updWrnngOn() | None |
The External released toggle (a.k.a. Emergency latched), keeps the On state since the moment the signal is debounced, and until an external signal is received. This kind of switch is used when an "abnormal situation" demands the push of the switch On, but a higher authority is needed to reset it to Off from a different signal source. Smoke, flood, intrusion alarms and "last man locks" are some examples of the use of this switch. As the external release signal can be physical or logical generated it can be implemented to be received from a switch or a remote signal of any usual kind. It's implemented in the XtrnUnltchMPBttn class.
Method | Parameters |
---|---|
XtrnUnLtchMPBttn | uint8_t mpbttnPin(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett(, unsigned long int strtDelay)))) |
XtrnUnLtchMPBttn | uint8_t mpbttnPin, DbncDlydMPBttn* unltchBttn(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett(, unsigned long int strtDelay)))) |
unlatch() | None |
The Time Voidable Momentary Button, keeps the ON state since the moment the signal is stable (debouncing process), plus a delay added, and until the moment the push button is released, or until a preset time in the ON state is reached. Then the switch will return to the Off position until the push button is released and pushed back. This kind of switches are used to activate limited resources related management or physical safety devices, and the possibility of a physical blocking of the switch to extend the ON signal artificially beyond designer's plans is highly undesired. Water valves, door unlocking mechanisms, hands-off security mechanisms, high power heating devices are some of the usual uses for these type of switches. It's implemented in the TmVdblMPBttn class.
Method | Parameters |
---|---|
TmVdblMPBttn | uint8_t mpbttnPin, unsigned long int voidTime(, bool pulledUp(, bool typeNO(, unsigned long int dbncTimeOrigSett(, unsigned long int strtDelay(, bool isOnDisabled))))) |
disable() | None |
enable() | None |
getIsEnabled() | None |
getIsOnDisabled() | None |
getIsVoided() | None |
getVoidTime() | None |
setIsEnabled() | bool enabledValue |
setIsOnDisabled() | bool isOnDisabledValue |
setIsVoided() | bool voidValue |
setVoidTime() | None |
updIsVoided() | None |