md
Push Button and LED on a Single GPIO Pin (old version)
October 8, 2019
<-Detecting Multiple Button Clicks in an Arduino Sketch Push Button and LED on a Single GPIO Pin->

The Sonoff SV has a populated 9 pin header that provides connections to three ESP8266 GPIO pins, ground and Vcc. Compared to a Sonoff Basic, access to three GPIO pins is a great improvement, but it is short of what I needed for an automatic garage door closer. So one GPIO pin has to do double duty: control a status light-emitting diode (LED) and read a normally open push button.

The push button will be used to disable or enable the automatic door closure. The red LED is turned on when the automatic function is disabled.

Here is how I connected the push button, LED and current limiting resistor.

The first schematic shows the circuit in its usual state. The GPIO pin is in output mode and set to low. Since 0 volts are across the LED it is off. In the next diagram to the right, the LED is turned on by setting the GPIO output pin to high. Since the switchis normally open, it has no effect in either case. The GPIO pin is set to input mode to read the state of the push button. When it is open (which will be the case almost always) the LED will be turned off. However the duration of this state is very short. Also the time between checks is relatively long so that visually, it will not be apparent that the LED is being turned off when checking the push button state. On those rare occasions that the push button is pressed, the LED will turn on, but that hopefully be seen as visual feedback.

It was not difficult to modify my original push button Arduino library to handle the LED. Here is the header file for the new library.

Please check newest version of this post and use the newest version of the mdButton library. The library described below should be used only in cases where the isButtonPressed_ routine in the updated mdButton library does not work properly.

 

#ifndef mdButtonLed_h #define mdButtonLed_h #include "Arduino.h" #define BUTTON_LED_ON 1 #define BUTTON_LED_OFF 0 #define DEFAULT_LED_START_STATE BUTTON_LED_ON #define DEFAULT_BUTTON_ACTIVE HIGH #define DEFAULT_DEBOUNCE_PRESS_TIME 15 #define DEFAULT_DEBOUNCE_RELEASE_TIME 30 #define DEFAULT_MULTI_CLICK_TIME 400 #define DEFAULT_HOLD_TIME 2000 #define DEFAULT_CHECK_INTERVAL 50 class mdButtonLed { public: mdButtonLed(uint8_t Pin, bool LedStartState = DEFAULT_LED_START_STATE, bool buttonActive = DEFAULT_BUTTON_ACTIVE); //constructor // Set attributes void setDebouncePressTime(uint16_t value); void setDebounceReleaseTime(uint16_t value); void setMultiClickTime(uint16_t value); void setHoldTime(uint16_t value); void setCheckInterval(uint16_t value); // status, number of clicks since last update // -1 = button held, 0 = button not pressed, 1, 2, ... number of times button pressed int buttonStatus(); // returns true if LED is on, false if LED is false bool ledStatus(void); void setLed(bool value); private: uint8_t pin_; bool active_; uint16_t debouncePressTime_ = DEFAULT_DEBOUNCE_PRESS_TIME; uint16_t debounceReleaseTime_ = DEFAULT_DEBOUNCE_RELEASE_TIME; uint16_t multiClickTime_ = DEFAULT_MULTI_CLICK_TIME; uint16_t holdTime_ = DEFAULT_HOLD_TIME; uint16_t checkInterval_ = DEFAULT_CHECK_INTERVAL; // State variables long lastButtonCheck_; long eventTime_; enum buttonState_t { AWAIT_PRESS, DEBOUNCE_PRESS, AWAIT_RELEASE, DEBOUNCE_RELEASE, AWAIT_MULTI_PRESS } buttonState_; int clicks_; bool ledState_; bool isButtonPressed(void); }; #endif

The constructor as a new parameter which is the state of the LED to be set when the buttonLed object is created. The button status function is renamed buttonStatus() and there is a new function, called ledStatus that returns true if the LED is lit and false otherwise. The setLed function is used to set the LED on or off independently of the state of the push button (at least logically). There is a new timing parameter which is the interval in milliseconds between successive tests of the button state. It can be defined with the setCheckInterval function. The library can also handle normally open push buttons that are active low.

When wiring the LED and switch in this fashion, it is necessary to activate the pull up resistor on the GPIO pin when putting it in input mode. Otherwise the value read will probably be low as if the switch was pressed.

To get about 1.8 V at a conservative 15 mA across a LED, a resistor of 100 ohms should be used in series with the LED with a 3.3 V power source. There are many LED calculators on the Web to help in arriving at the value of the current limiting resistor: ledcacl.com, ledcalculator.net ... If these components are at the end of a long cable to the Sonoff SV, it would be a good idea to measure the supply voltage at the LED in order to account for the resistance of the wire. Finally, the diagram on the right is to remind me of which pin is the anode, which I am always forgetting.

The library can be downloaded here: mdButtonLed.zip.

<-Detecting Multiple Button Clicks in an Arduino Sketch Push Button and LED on a Single GPIO Pin->