Raspberry Pi Pico: How to Read a Push Button

Raspberry Pi Pico Basics: Reading a Push Button and Controlling an LED

Abstract

This article guides you through configuring a GPIO pin as an input to read the state of an external push button on the Raspberry Pi Pico. We will use the input to control the state of an LED, demonstrating fundamental input/output interaction. The project utilizes the C/C++ Pico SDK, and includes printf over the USB serial port for simple debugging and status indication.

1. Introduction

The core functionality of embedded systems involves not only controlling outputs (like blinking an LED) but also reading inputs from the environment (like a button press). This tutorial shows you how to integrate user input using a push button to control an LED’s state.

This guide will cover:

  • Setting up the necessary hardware circuit with an external LED and a push button.
  • Configuring a GPIO pin as an input using an internal pull-up resistor.
  • Reading the button’s state using the Pico SDK functions.
  • Using the button press to toggle an LED’s state and printing status updates with printf for debugging.

2. Prerequisites and Hardware Setup

To follow this tutorial, you will need:

Hardware Components:

    • Raspberry Pi Pico board.
    • LED (can be the onboard one).
    • Push Button (momentary tactile switch – KY-004).
    • Breadboard and jumper wires.
    • A Micro-USB cable for power, flashing, and serial communicatio

Software/Environment:

      • VS Code (Visual Studio Code).
      • Raspberry Pi Pico/RP2040 Extension for VS Code.
      • The Pico SDK and necessary build tools (typically managed by the VS Code extension).

Circuit Connections

For this example, we will use two dedicated external GPIO pins:

  • LED Output Pin: Connect the LED (via resistor) to GPIO 25.
  • Button Input Pin: Connect one side of the push button to GPIO 21 and the other side to GND (Ground).

Note on Pull-Up: We connect the button to GND so that we can use the Pico’s internal pull-up resistor. This keeps the input pin pulled HIGH (1) when the button is not pressed. Pressing the button connects the pin to GND, pulling the state LOW (0).

3. Setting Up the VS Code Project

We’ll use the Pico VS Code Extension’s functionality to quickly generate a project structure.

Step 1 – Launch VS Code

  • Open VS Code.

Step 2 – Create a New Project

  • Press Ctrl + Shift + P (or Cmd + Shift + P on Mac) to open the Command Palette.
  • Type and select “Pico: New Project”:
  • Choose “C/C++”.
  • Select an empty folder for your project (e.g., ~/pico-projects/HackerButtonControl).
  • Name your project (e.g., HackerButtonControl).
  • Select the Board type (e.g., Pico):
  • Choose the Stdio support “Console over USB” and Crete the Project:

Step 3 – Verify CMake Configuration

Ensure your project’s CMakeLists.txt file links the necessary libraries for GPIO and standard I/O (required for printf):

  • CMake
  • target_link_libraries(ButtonControl pico_stdlib)

4. Writing the Input/Output C/C++ Code

Open the main source file (usually main.c in the project’s root). We’ll add the necessary includes, define the LED and BUTTON pins, and implement the reading and blinking logic.

Key Code Components

We need to include the standard Pico libraries and use the provided functions:

  • pico/stdlib.h: Includes basic Pico functions.
  • hardware/gpio.h: Required for all GPIO functions.
  • pico/time.h: Required for the sleep_ms() delay function.
  • stdio.h: For the printf function.

Complete main.c Code

				
					#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"


// Define the GPIO pins based on your circuit setup
#define LED_PIN 25
#define BUTTON_PIN 21


int main()
{
  // 1. Initialize Standard I/O (for printf over USB serial)
    stdio_init_all();
    printf("--- Pico Push Button Input Demo Started! ---\n");
   
    // 2. Configure LED Pin (Output)
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);
    gpio_put(LED_PIN, 0); // Start with LED OFF
    printf("LED (GPIO %d) configured as output.\n", LED_PIN);

    // 3. Configure Button Pin (Input with Pull-Up)
    gpio_init(BUTTON_PIN);
    gpio_set_dir(BUTTON_PIN, GPIO_IN); // Set pin as input
   
    // Enable internal PULL-UP resistor. Input is HIGH (1) when button is open.
    gpio_pull_up(BUTTON_PIN);
    printf("Button (GPIO %d) configured as input with pull-up. Active LOW.\n", BUTTON_PIN);

    bool led_state = false; // Tracks the current state of the LED
    int last_button_state = 1; // Start state: Unpressed (HIGH)

    while (true) {
        // Read the current state of the button (0 = Pressed, 1 = Unpressed)
        int current_button_state = gpio_get(BUTTON_PIN);
       
        // Detect a transition from Unpressed (1) to Pressed (0)
        if (current_button_state == 0 && last_button_state == 1) {
           
            // A press event occurred (rising edge detection in reverse)
            led_state = !led_state; // Toggle the LED state
            gpio_put(LED_PIN, led_state); // Apply the new state to the LED
           
            printf(">>> Button Pressed! LED Toggled to %s. <<<\n", led_state ? "ON" : "OFF");
           
            // Short delay for rudimentary software debouncing
            sleep_ms(50);
        }
       
        // Update the last state for the next loop iteration
        last_button_state = current_button_state;
       
        // Prevent excessive CPU usage
        sleep_ms(10);
    }
    return 0;
}

				
			

Code Explanation

  • stdio_init_all(): This crucial function initializes all standard I/O, which, for the Pico, defaults to communicating over the USB connection (Virtual COM Port) for printf.
  • gpio_init(): Initializes the selected GPIO pin.
  • gpio_set_dir(): Configures the pin to be an Output.
  • gpio_put(): Sets the pin state to High (1), which usually turns the LED ON.
  • gpio_put(): Sets the pin state to Low (0), which usually turns the LED OFF.
  • sleep_ms(): Halts the program execution for x milliseconds.
  • printf(…): Prints a message to the serial console every time the LED state changes, confirming that the code is running and functioning as expected.
  • gpio_pull_up(): Enables the internal pull-up resistor, ensuring a stable HIGH (1) reading when the button is idle.
  • gpio_get(): Returns the pin state.

5. Compiling, Flashing, and Testing

Step 1 – Build the Project

  • Click the “Build” icon in the VS Code bottom toolbar, or use the shortcut Ctrl + Shift + B.

The build process will generate a *.uf2 and the usual binaries (*.bin, *.hex and *.elf) file in your build folder.

Step 2 – Flash the Code

  1. Enter BOOTSEL Mode: Hold down the BOOTSEL button on your Pico and plug the USB cable into your PC. Release the button. Your Pico should appear as a removable drive named RPI-RP2.
  2. Click on the Run icon, the *.elf file will be loaded into the board’s memory:

Alternatively:

  1. Drag and Drop: Locate the generated .uf2 file in your project’s build directory (e.g., build/HackerBlink.uf2).
  2. Drag and drop the .uf2 file onto the RPI-RP2 drive. The Pico will automatically reboot, and the new program will start running.

Step 3 – Testing with printf Output

Open the Serial Monitor: In VS Code, it should be readily available, if not, press Ctrl+Shift+P and type “serial monitor”:

Locate the proper COM and click Start Monitoring:

Confirm Output: You should see the printf messages appearing in the serial console:

  • >>> Button Pressed! LED Toggled to ON. <<<
  • >>> Button Pressed! LED Toggled to OFF. <<<

Check the LED: The on-board LED on your Raspberry Pi Pico should toggle upon button press.

6. Hands-On Lab Recap

In this introductory article, you successfully:

  • Created a C/C++ project for the Raspberry Pi Pico using the VS Code extension.
  • Learned to initialize and configure a GPIO pin as an output.
  • Used the Pico SDK functions like gpio_init(), gpio_set_dir(), gpio_put(), gpio_get(),and sleep_ms().
  • Implemented printf for basic status and debugging over the USB serial port.
  • Compiled, flashed, and tested your read button project.

7. Common Issues & Fixes

Issue Cause Solution
LED doesn't blink Wrong GPIO pin defined or LED circuit error (if external). Ensure #define LED_PIN 25 is used for the on-board LED. Check external circuit for correct resistor and polarity.
Code doesn't run / RPI-RP2 drive doesn't appear Pico isn't in BOOTSEL mode or faulty USB cable. Unplug and replug the USB cable while holding the BOOTSEL button. Try a different cable.
No printf output stdio_init_all() is missing or the serial monitor is not connected/at the wrong speed. Ensure stdio_init_all(); is at the start of main(). Check your serial monitor connection and baud rate (usually 115200).
Compilation error Missing includes or incorrect CMakeLists.txt. Ensure you have #include "pico/stdlib.h", etc., and that pico_stdlib is linked in CMakeLists.txt.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top