2. Chapter Button and leds
Usually, there are three essential parts in a complete automatic control device: INPUT, OUTPUT, and CONTROL. In last section, the LED module was the output part and RPI was the control part. In practical applications, we not only make LEDs flash, but also make a device sense the surrounding environment, receive instructions and then take the appropriate action such as turn on LEDs, make a buzzer beep and so on.
Next, we will build a simple control system to control an LED through a push button switch.
2.1. Project Push Button Switch & LED
In the project, we will control the LED state through a Push Button Switch. When the button is pressed, our LED will turn ON, and when it is released, the LED will turn OFF. This describes a Momentary Switch.
2.1.1. Component List
Raspberry Pi (Recommended: Raspberry Pi 5 / 4B / 3B+ / 3B) (Compatible: 3A+ / 2B / 1B+ / 1A+ / Zero W / Zero) |
|||
LED x1 |
Breadboard x1 |
||
GPIO Extension Board & Ribbon Cable |
|||
Push Button Switch x1 |
Resistor 10KΩ x2 |
Resistor 220Ω x1 |
|
Jumper (some) |
|||
Note
In the code “button” represents switch action.
2.1.2. Component knowledge
2.1.2.1. Push Button Switch
This type of Push Button Switch has 4 pins (2 Pole Switch). Two pins on the left are connected, and both left and right sides are the same per the illustration:
When the button on the switch is pressed, the circuit is completed (your project is Powered ON).
2.1.3. Circuit
Schematic diagram
Note
R3 is used to limit current to protect GPIO 18, if you set it to output HIGH level by mistake.
Hardware connection
Note
There are two kinds of push button switch in this kit.
The smaller push button switches are contained in a plastic bag.
Hint
If you need any support, please feel free to contact us via: support@freenove.com
This is how it works.
When button switch is released:
When button switch is pressed:
2.1.4. Code
This project is designed for learning how to use Push Button Switch to control an LED. We first need to read the state of switch, and then determine whether to turn the LED ON in accordance to the state of the switch.
2.1.4.1. C Code ButtonLED
First, observe the project result, then learn about the code in detail.
Hint
If you need any support, please feel free to contact us via: support@freenove.com
Use
cdcommand to enterButtonLEDdirectory of C code.
$ cd ~/Freenove_Kit/Code/C_Code/02.1.1_ButtonLED
Use the following command to compile the code
ButtonLED.cand generate executable fileButtonLED.
$ gcc ButtonLED.c -o ButtonLED -lwiringPi
Then run the generated file
ButtonLED.
$ sudo ./ButtonLED
Later, the terminal window continues to print out the characters “led off…”. Press the button, then LED is turned on and then terminal window prints out the “led on…”.
Release the button, then LED is turned off and then terminal window prints out the “led off…”. You can press Ctrl+C to terminate the program.
The following is the program code:
1/**********************************************************************
2* Filename : ButtonLED.c
3* Description : Control led by button.
4* Author : www.freenove.com
5* modification: 2019/12/26
6**********************************************************************/
7#include <wiringPi.h>
8#include <stdio.h>
9
10#define ledPin 0 //define the ledPin
11#define buttonPin 1 //define the buttonPin
12
13void main(void)
14{
15 printf("Program is starting ... \n");
16
17 wiringPiSetup(); //Initialize wiringPi.
18
19 pinMode(ledPin, OUTPUT); //Set ledPin to output
20 pinMode(buttonPin, INPUT);//Set buttonPin to input
21
22 pullUpDnControl(buttonPin, PUD_UP); //pull up to HIGH level
23 while(1){
24 if(digitalRead(buttonPin) == LOW){ //button is pressed
25 digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
26 printf("Button is pressed, led turned on >>>\n"); //Output information on terminal
27 }
28 else { //button is released
29 digitalWrite(ledPin, LOW); //Make GPIO output LOW level
30 printf("Button is released, led turned off <<<\n"); //Output information on terminal
31 }
32 }
33}
In the circuit connection, LED and Button are connected with GPIO17 and GPIO18 respectively, which correspond to 0 and 1 respectively in wiringPI. So define ledPin and buttonPin as 0 and 1 respectively.
1#define ledPin 0 //define the ledPin
2#define buttonPin 1 //define the buttonPin
In the while loop of main function, use digitalRead(buttonPin) to determine the state of Button. When the button is pressed, the function returns low level, the result of “if” is true, and then turn on LED. Or, turn off LED
1if(digitalRead(buttonPin) == LOW){ //button is pressed
2 digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
3 printf("Button is pressed, led turned on >>>\n"); //Output information on terminal
4}
5else { //button is released
6 digitalWrite(ledPin, LOW); //Make GPIO output LOW level
7 printf("Button is released, led turned off <<<\n"); //Output information on terminal
8}
2.1.4.2. Reference
- int digitalRead (int pin);
This function returns the value read at the given pin. It will be “HIGH” or “LOW”(1 or 0) depending on the logic level at the pin.
2.2. Project MINI Table Lamp
We will also use a Push Button Switch, LED and RPi to make a MINI Table Lamp but this will function differently: Press the button, the LED will turn ON, and pressing the button again, the LED turns OFF. The ON switch action is no longer momentary (like a door bell) but remains ON without needing to continually press on the Button Switch.
First, let us learn something about the push button switch.
2.2.1. Debounce a Push Button Switch
When a Momentary Push Button Switch is pressed, it will not change from one state to another state immediately. Due to tiny mechanical vibrations, there will be a short period of continuous buffeting before it stabilizes in a new state too fast for Humans to detect but not for computer microcontrollers. The same is true when the push button switch is released. This unwanted phenomenon is known as “bounce”.
Therefore, if we can directly detect the state of the Push Button Switch, there are multiple pressing and releasing actions in one pressing cycle. This buffeting will mislead the high-speed operation of the microcontroller to cause many false decisions. Therefore, we need to eliminate the impact of buffeting. Our solution: to judge the state of the button multiple times. Only when the button state is stable (consistent) over a period of time, can it indicate that the button is actually in the ON state (being pressed).
This project needs the same components and circuits as we used in the previous section.
2.2.2. Code
In this project, we still detect the state of Push Button Switch to control an LED. Here we need to define a variable to define the state of LED. When the button switch is pressed once, the state of LED will be changed once. This will allow the circuit to act as a virtual table lamp.
2.2.2.1. C Code Tablelamp
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@freenove.com
Use cd command to enter 02.2.1_Tablelamp directory of C code.
$ cd ~/Freenove_Kit/Code/C_Code/02.2.1_Tablelamp
Use the following command to compile “Tablelamp.c” and generate executable file “Tablelamp”.
$ gcc Tablelamp.c -o Tablelamp -lwiringPi
Tablelamp: Then run the generated file “Tablelamp”.
$ sudo ./Tablelamp
When the program is executed, press the Button Switch once, the LED turns ON. Pressing the Button Switch again turns the LED OFF.
1/**********************************************************************
2* Filename : Tablelamp.c
3* Description : DIY MINI table lamp
4* Author : www.freenove.com
5* modification: 2019/12/27
6**********************************************************************/
7#include <wiringPi.h>
8#include <stdio.h>
9
10#define ledPin 0 //define the ledPin
11#define buttonPin 1 //define the buttonPin
12int ledState=LOW; //store the State of led
13int buttonState=HIGH; //store the State of button
14int lastbuttonState=HIGH;//store the lastState of button
15long lastChangeTime; //store the change time of button state
16long captureTime=50; //set the stable time for button state
17int reading;
18int main(void)
19{
20 printf("Program is starting...\n");
21
22 wiringPiSetup(); //Initialize wiringPi.
23
24 pinMode(ledPin, OUTPUT); //Set ledPin to output
25 pinMode(buttonPin, INPUT); //Set buttonPin to input
26
27 pullUpDnControl(buttonPin, PUD_UP); //pull up to high level
28 while(1){
29 reading = digitalRead(buttonPin); //read the current state of button
30 if( reading != lastbuttonState){ //if the button state has changed, record the time point
31 lastChangeTime = millis();
32 }
33 //if changing-state of the button last beyond the time we set, we consider that
34 //the current button state is an effective change rather than a buffeting
35 if(millis() - lastChangeTime > captureTime){
36 //if button state is changed, update the data.
37 if(reading != buttonState){
38 buttonState = reading;
39 //if the state is low, it means the action is pressing
40 if(buttonState == LOW){
41 printf("Button is pressed!\n");
42 ledState = !ledState; //Reverse the LED state
43 if(ledState){
44 printf("turn on LED ...\n");
45 }
46 else {
47 printf("turn off LED ...\n");
48 }
49 }
50 //if the state is high, it means the action is releasing
51 else {
52 printf("Button is released!\n");
53 }
54 }
55 }
56 digitalWrite(ledPin,ledState);
57 lastbuttonState = reading;
58 }
59
60 return 0;
61}
This code focuses on eliminating the buffeting (bounce) of the button switch. We define several variables to define the state of LED and button switch. Then read the button switch state constantly in while () to determine whether the state has changed. If it has, then this time point is recorded.
1reading = digitalRead(buttonPin); //read the current state of button
2if( reading != lastbuttonState){ //if the button state has changed, record the time point
3 lastChangeTime = millis();
4}
- millis()
This returns a number representing the number of milliseconds since your program called one of the wiringPiSetup functions. It returns to an unsigned 32-bit number value after 49 days because it “wraps” around and restarts to value 0.
Then according to the recorded time point, evaluate the duration of the button switch state change. If the duration exceeds captureTime (buffeting time) we have set, it indicates that the state of the button switch has changed. During that time, the while () is still detecting the state of the button switch, so if there is a change, the time point of change will be updated. Then the duration will be evaluated again until the duration is determined to be a stable state because it exceeds the time value we set.
1if(millis() - lastChangeTime > captureTime){
2 //if button state is changed, update the data.
3 if(reading != buttonState){
4 buttonState = reading;
Finally, we need to judge the state of Button Switch. If it is low level, the changing state indicates that the button Switch has been pressed, if the state is high level, then the button has been released. Here, we change the status of the LED variable, and then update the state of the LED.
1if(buttonState == LOW){
2 printf("Button is pressed!\n");
3 ledState = !ledState; //Reverse the LED state
4 if(ledState){
5 printf("turn on LED ...\n");
6 }
7 else {
8 printf("turn off LED ...\n");
9 }
10}







