Arduino Activity 3: Push Button

Arduino Activity 3: Push Button

by ACROBOTIC Industries

Overview

Time to complete: 2–10min; Level of difficulty: Beginner

In this activity, we’ll build an electronic circuit with an LED and a push button; we’ll program our Arduino board to turn the LED on or off depending on whether we press, hold, or release the push button!

List of Materials

  • 1 x Arduino Uno R3
  • 1 x USB-A to USB-B Male / Male Cable
  • 1 x 3mm Color LED Set (10-Pack)
  • 1 x 6mm x 6mm Momentary Switch
  • 1 x Resistor 1/4W Through Hole (1KOhm)
  • 1 x Jumper Wires Male/Male - 10-pack
  • 1 x Mounting Plate for Arduino Uno
  • 1 x Half-Sized Solderless Breadboard

Obtaining the Code

For this activity, we'll be loading 2 different programs to our Arduino Uno board, which are available in our Github repository:

We can open a new window in the Arduino environment and copy-paste the code.  We'll start out with the program Button Hold.


Wiring: Button Hold

In our LEDs tutorial, we learned how to recognize the proper polarity of an LED.  Recalling that the positive (longer) lead should match the lead with the little kink on the wiring diagram below, we proceed to wire up the circuit.

As for the push button, even for experienced users these 6mm x 6mm tactile switches can be tricky to connect properly.  The main challenge is recognizing their correct orientation prior to placing it on the breadboard; to do this, we need to use the pins of the button as reference.  As the pins protrude from the button's casing on opposite sides, we rotate the button so that the pins face sideways relative to the breadboard (towards the blue/red power rails!).

The resistor value used for limiting the current flow through the LED is 1KOhm (Brown-Black-Red).


Using Pull-up/Pull-down Resistors with Digital Inputs

Connecting one pin of the button to ground (GND) and the other directly to the pin on the Arduino board (pin 2) minimizes the wiring of the circuit, and allows us to send a digital LOW signal to the Arduino pin when the putton is pressed.  The question now is, what happens before the button is pressed?  Specifically, what value or signal does the Arduino pin receive?

Well, the datasheet of the ATmega328p microcontroller on our Arduino board tells us that the default state for a digital I/O pin is as an input.  In this state, the pin is 'floating' (i.e., in a high-impedance state) and it can switch between reading a digial HIGH or LOW erratically.  By connecting an input pin to either GND or VCC guarantees that it will always read one value OR the other.  Typically, we don't want this connection to be direct, but rather through a current-limiting resistor.  A resistor serving the function of tying an input pin to HIGH or LOW are commonly known as pull-up or pull-down, respectively.

In fact, pull-up resistors are so commonly used in microcontroller applications that these devices include internal ones that can be easily enabled and disabled.  They are convenient, and help reduce the number of components and wiring needed.  The value of this resistors in the case of the ATmega328p is between 20K–40KOhms.

MCU Internal Pull-Up Resistor Diagram


Code Walkthrough: Button Hold

Now that the wiring of the push button is understood, let's analyze the code in the Button Hold program.  After declaring the variables we'll be using in the rest of the code, we initialize the pins for their respective function.  This is where we configure the ATmega328p microcontroller to use its internal pull-up resistor on pin 2:

  // Initialize the pushbutton pin as an input that is internally pulled up
  // to 5V using the built-in 20~50K resistors (ATmega328p on the Arduino Uno)
  pinMode(button_pin, INPUT_PULLUP);  

Then we move to our loop() function.  The first thing we want to do is read the state of the button.  As we have the button connected to VCC through the internal pull-up resistor, we expect the state to be digital HIGH unless the push button is pressed (in which case it will be digital LOW).

  // Read the state of the push button value:
  button_state = digitalRead(button_pin); // pulled up to 5V by default 

We then implement the logic that will control the state of the LED (on/off) depending on the state of the push button.  That is, while the button is pressed we want the LED to stay on, otherwise we want it to be off.  For that:

  // Check if the push button is pressed. If it is, the button state is 
  // LOW because the button is connected to ground:
  if (button_state == LOW) 
  {
    // Turn LED on:    
    digitalWrite(led_pin, HIGH);  
  }
  // otherwise (i.e., if button_state is HIGH)
  else 
  {
    // Turn LED off:
    digitalWrite(led_pin, LOW);
  }

This works quite well, but at times you'll see that the LED will behave erratically.  In particular, it might switch between on and off states rapidly even when the push button had not been pressed or realeased.  This erractic on-off toggling usually occurs right after we've pressed or released the button, and it's typically due to a phenomenon known as bouncing.

Let's go ahead and test the program by uploading the code to the Arduino Uno board.


Fixing Switch Bouncing with Software

Bouncing in the context of electromechanical switches, is a phenomenon that occurs due to the kinetic energy that is generated when two (or more) contacts come together after a force is applied.  While the kinetic energy settles, there is some physical "ringing" of the contacts, which affects the electrical signal that is transmitted through the contacts.  Whereas the phenomenon tends to be more significant when switches are closed, it can also be present when they're opened.

Although bouncing occurs with all different types of switches (e.g., sliding, pushbutton), there are some better than others.  Typically, wetted contacts such as mercury-based ones are better.  In addition, depending on the quality of the switch we can see that some can take up a few tens of milliseconds to settle, whereas the better quality ones do so within a few (< 5ms) instants.

Whereas the rapid, transient bouncing of a digital signal doesn't typically have negative too many repercussions on the hardware, it can affect the behavior of a program running in a microcontroller.  We saw this when we pressed/released the button in the previous step, and the LED turned on/off erratically until the contact settled.  We can address this problem in two (non mutually-exclusive) ways: using additional hardware and/or modifying our software.

  if (button_state == LOW) 
  {
    // Turn LED on:    
    digitalWrite(led_pin, HIGH);
    delay(200); // quick and dirty debouncing
  }
  // otherwise (i.e., if button_state is HIGH)
  else 
  {
    // Turn LED off:
    digitalWrite(led_pin, LOW); 
    delay(200); // quick and dirty debouncing
  }

A very easy solution for the Button Hold program is to add a delay of ~200ms right after we change the state of the LED.  Whereas this would perhaps make the program not respond as quickly as we may desire, we wouldn't see the LED rapidly toggling on/off right after the button is pressed or released.  A more sophisticated strategy is implemented in the Button Toggle program below.


Code Walkthrough: Button Toggle

With a bit more insight into the Switch Bouncing phenomenon, we can go ahead and upload the Button Toggle program to our Arduino board.  As the name suggests, the idea is to have the LED change its on/off state when the button is pressed.  Different than in the Button Hold program, however, we want the LED to maintain its state until the button is pressed again.  For this, our loop() function now includes the following lines of code:

  if ( (button_state == HIGH) && 
       (button_state_old == LOW) && 
       ((millis() - time) > bounce_wait) ) 
  {
    // Check the previous state of the LED and toggle it
    if (led_state == HIGH)
      led_state = LOW;
    else
      led_state = HIGH;
    // Store the current time for comparison in the next loop iteration 
    time = millis();    
  }

We're using the built-in function millis() to get the number of milliseconds since the Arduino board began running the current program.  The code uses a variable, time, to store the last value of millis() when the button was pressed (initially set to zero).  Using this variable, we can compute how much time has passed since the last time the button was pressed through the operation millis()-time .  Then we compare the difference with a threshold (bounce_wait) and decide whether the button press is genuine, or perhaps caused by an spurious voltage change due to the Bouncing phenomenon.


Code Tinkering

As an exercise we invite you to try and add one more push button to Button Toggle code sample.  It'd be great to use one push button for turning the LED on, and a second one for turning it off.  The wiring would be similar for the second push button, but instead of connecting it to digital pin 2 we would connect it to any other digital pin.

Leave a comment

  • Please note, comments must be approved before they are published

$1 Days
$2 Hours
$3 Minutes
$4 Second
{ "en":{ "general": { "field": { "required": "Required", "actions": "Actions", "top_btn": "Top" }, "accessibility": { "skip_to_content": "Skip to content", "close_modal": "Close (esc)" }, "meta": { "tags": "Tagged \"[[ tags ]]\"", "page": "Page [[ page ]]" }, "404": { "title": "404 Page Not Found", "subtext": "The page you requested does not exist.", "link": "Continue shopping" }, "pagination": { "previous": "Previous", "next": "Next", "current_page": "Page [[ current ]] of [[ total ]]" }, "password_page": { "opening_soon": "Opening Soon", "login_form_heading": "Enter store using password", "login_form_password_label": "Password", "login_form_password_placeholder": "Your password", "login_form_submit": "Enter", "signup_form_email_label": "Email", "signup_form_success": "We will send you an email right before we open!", "admin_link_html": "Are you the store owner? Log in here<\/a>", "password_link": "Enter using password", "powered_by_shopify_html": "This shop will be powered by [[ shopify ]]" }, "social": { "share_on_facebook": "Share", "share_on_twitter": "Tweet", "share_on_pinterest": "Pin it", "alt_text": { "share_on_facebook": "Share on Facebook", "share_on_twitter": "Tweet on Twitter", "share_on_pinterest": "Pin on Pinterest" } }, "search": { "no_results_html": "Your search for \"[[ terms ]]\" did not yield any results.", "results_with_count": { "one": "[[ count ]] result for \"[[ terms ]]\"", "other": "[[ count ]] results for \"[[ terms ]]\"" }, "title": "Search our site", "placeholder": "Search", "submit": "Submit", "close": "Close search" }, "newsletter_form": { "newsletter_email": "Join our mailing list", "email_placeholder": "Email address", "confirmation": "Thanks for subscribing", "submit": "Subscribe", "show_me_text": "Do not show me again" }, "filters": { "show_more": "Show More", "show_less": "Show Less" }, "breadcrumbs": { "home": "Home", "create_account": "Create account", "account": "Account", "addresses": "Addresses" }, "item": { "remove": "Remove Item" } }, "sections": { "header": { "top_header_login": "Login", "top_header_register": "Register", "top_header_wishlist": "Wish list", "register_dropdown": "No account? Create one here", "forgot": "Forgot password", "all_collection": "All Collections", "world_wide_delivery": "Worldwide delivery", "shipping_text": "Free UK Delivery on orders over £ 100", "hot_line": "Hot line" }, "menu": { "mobile_menu_tab": "Menu", "mobile_account_tab": "Account", "mobile_settings_tab": "Settings" }, "slideshow": { "next_slide": "Next slide", "previous_slide": "Previous slide", "pause_slideshow": "Pause slideshow", "play_slideshow": "Play slideshow", "play_video": "Play video", "close_video": "Close video" }, "map": { "get_directions": "Get directions", "address_error": "Error looking up that address", "address_no_results": "No results for that address", "address_query_limit_html": "You have exceeded the Google API usage limit. Consider upgrading to a Premium Plan<\/a>.", "auth_error_html": "There was a problem authenticating your Google Maps account. Create and enable the JavaScript API<\/a> and Geocoding API<\/a> permissions of your app." } }, "blogs": { "article": { "view_all": "View all", "all_topics": "All topics", "by_author": "by [[ author ]]", "posted_in": "Posted in", "read_more": "Read more", "back_to_blog": "Back to [[ title ]]" }, "comments": { "title": "Leave a comment", "name": "Name", "email": "Email", "message": "Message", "post": "Post comment", "moderated": "Please note, comments must be approved before they are published", "success_moderated": "Your comment was posted successfully. We will publish it in a little while, as our blog is moderated.", "success": "Your comment was posted successfully! Thank you!", "comments_with_count": { "one": "[[ count ]] comment", "other": "[[ count ]] comments" } } }, "cart": { "general": { "title": "Your cart", "note": "Add a note to your order", "remove": "Remove", "subtotal": "Subtotal", "savings": "You're saving", "shipping_at_checkout": "Shipping & taxes calculated at checkout", "update": "Update", "checkout": "Process Check out", "empty": "Your cart is currently empty.", "cookies_required": "Enable cookies to use the shopping cart", "edit": "Edit", "cancel": "Cancel", "continue_shopping": "Continue shopping", "recently_added_item": "Recently added item(s)", "remove_item": "Remove This Item", "view_and_edit_cart": "View and edit cart", "clear": "Clear cart", "empty_page_title": "Shopping Cart is Empty", "here": "here", "empty_continue_html": "Click here to continue shopping.", "processing": "Processing...", "items_count_label" : "[[ count ]] item(s) in your cart", "ok" : "Ok" }, "label": { "product": "Product", "price": "Price", "quantity": "Quantity", "total": "Total", "total_item": "Total item", "sub_total_top": "Cart Subtotal" } }, "collections": { "general": { "view_all": "View all", "clear_all": "Clear All", "no_matches": "Sorry, there are no products in this collection", "items_with_count": { "one": "[[ count ]] product", "other": "[[ count ]] products" }, "load_more": "Load More", "sidebar_btn": "Filter by" }, "sorting": { "title": "Sort by", "manual": "Featured", "best_selling": "Best Selling", "title_ascending": "Alphabetically, A-Z", "title_descending": "Alphabetically, Z-A", "price_ascending": "Price, low to high", "price_descending": "Price, high to low", "created_descending": "Date, new to old", "created_ascending": "Date, old to new" }, "filters": { "title_tags": "Filter", "all_tags": "All products", "categories": "categories", "title": "Filter", "color": "Color", "size": "Size", "brand": "Brand", "price": "Price", "green": "Green", "blue": "Blue", "red": "Red", "pink": "Pink", "black": "Black", "purple": "Purple", "white": "White", "orange": "Orange" }, "product_item": { "quick_shop": "Quick View", "compare": "Compare", "wishlist": "Add to Wishlist" } }, "contact": { "form": { "name": "Name", "email": "Email", "phone": "Phone Number", "message": "Message", "submit": "Submit", "post_success": "Thanks for contacting us. We'll get back to you as soon as possible.", "address": "Address", "telephone": "Telephone", "title": "Write us", "required": "Required" } }, "customer": { "account": { "title": "My Account", "details": "Account Details", "view_addresses": "View Addresses", "return": "Return to Account Details" }, "activate_account": { "title": "Activate Account", "subtext": "Create your password to activate your account.", "password": "Password", "password_confirm": "Confirm Password", "submit": "Activate Account", "cancel": "Decline Invitation" }, "addresses": { "title": "Your Addresses", "default": "Default", "add_new": "Add a New Address", "edit_address": "Edit address", "first_name": "First Name", "last_name": "Last Name", "company": "Company", "address1": "Address1", "address2": "Address2", "city": "City", "country": "Country", "province": "Province", "zip": "Postal\/Zip Code", "phone": "Phone", "set_default": "Set as default address", "add": "Add Address", "update": "Update Address", "cancel": "Cancel", "edit": "Edit", "delete": "Delete", "delete_confirm": "Are you sure you wish to delete this address?" }, "login": { "title": "Login", "desc": "If you have an account, sign in with your email address.", "email": "Email", "password": "Password", "forgot_password": "Forgot your password?", "sign_in": "Sign In", "guest_title": "Continue as a guest", "guest_continue": "Continue" }, "orders": { "title": "Order History", "order_number": "Order", "date": "Date", "payment_status": "Payment Status", "fulfillment_status": "Fulfillment Status", "total": "Total", "none": "You haven't placed any orders yet." }, "order": { "title": "Order [[ name ]]", "date": "Placed on [[ date ]]", "cancelled": "Order Cancelled on [[ date ]]", "cancelled_reason": "Reason: [[ reason ]]", "billing_address": "Billing Address", "payment_status": "Payment Status", "shipping_address": "Shipping Address", "fulfillment_status": "Fulfillment Status", "discount": "Discount", "shipping": "Shipping", "tax": "Tax", "product": "Product", "sku": "SKU", "price": "Price", "quantity": "Quantity", "total": "Total", "fulfilled_at": "Fulfilled [[ date ]]", "subtotal": "Subtotal" }, "recover_password": { "title": "Reset your password", "email": "Email", "submit": "Submit", "cancel": "Cancel", "subtext": "We will send you an email to reset your password.", "success": "We've sent you an email with a link to update your password." }, "reset_password": { "title": "Reset account password", "subtext": "Enter a new password for [[ email ]]", "password": "Password", "password_confirm": "Confirm Password", "submit": "Reset Password" }, "register": { "title": "Create Account", "first_name": "First Name", "last_name": "Last Name", "email": "Email", "password": "Password", "submit": "Create", "desc": "Creating an account is easy. Just fill in the form below." } }, "homepage": { "onboarding": { "product_title": "Your product's name", "product_description": "This area is used to describe your product’s details. Tell customers about the look, feel, and style of your product. Add details on color, materials used, sizing, and where it was made.", "collection_title": "Your collection's name", "blog_title": "Your post's title", "blog_excerpt": "Your store hasn’t published any blog posts yet. A blog can be used to talk about new product launches, tips, or other news you want to share with your customers. You can check out Shopify’s ecommerce blog for inspiration and advice for your own store and blog.", "blog_author": "Author name", "no_content": "This section doesn’t currently include any content. Add content to this section using the sidebar." } }, "layout": { "navigation": { "search": "Search", "toggle": "expand\/collapse", "expand": "expand", "collapse": "collapse", "all_categories": "All Categories" }, "cart": { "title": "Cart", "items_count": { "one": "item", "other": "items" } }, "customer": { "account": "Account", "log_out": "Log out", "logout": "Log out", "log_in": "Log in", "create_account": "Create account", "sign_up": "Sign up", "wishlist": "Wishlist" }, "footer": { "social_platform": "[[ name ]] on [[ platform ]]" }, "list_page": { "grid": "Grid", "list": "List" } }, "products": { "product": { "regular_price": "Regular price", "sold_out": "Sold out", "unavailable": "Unavailable", "on_sale": "Sale", "quantity": "Quantity", "add_to_cart": "Add to cart", "back_to_collection": "Back to [[ title ]]", "related_title": "Related Products", "qty_increase": "Increase", "qty_decrease": "Decrease", "deal_days": "Days", "deal_hours": "Hours", "deal_minutes": "Minutes", "deal_second": "Second", "select_option": "Select Option", "add_to_wishlist": "Add to Wishlist", "add_to_review": "Add to review", "compare_success_msg": "[[ product_title ]] has added to comparing box successful", "compare_exist_msg": "[[ product_title ]] is exist in comparing box", "compare_cart_msg": "[[ product_title ]] has added to shopping cart", "compare_remove_msg": "[[ product_title ]] has removed from comparing box", "compare_remove_msg": "[[ product_title ]] has removed from comparing box", "comparing_box": "Comparing box", "compare_no_items": "There is no items in comparing box", "wishlist_success_msg": "[[ product_title ]] has added to wishlist successful", "wishlist_exist_msg": "[[ product_title ]] is exist in wishlist", "wishlist_cart_msg": "[[ product_title ]] has added to shopping cart", "wishlist_box": "Wishlist", "wishlist_remove_msg": "[[ product_title ]] has removed from wishlist", "wislist_no_items": "There is no items in wishlist", "upsell_cart_msg": "\"[[ product_title ]]\" has added to shopping cart", "upsell_block_title": "Frequently bought with \"[[ product_title ]]\"", "upsell_cart_qty": "[[ count ]] item(s)", "upsell_product_page_title": "You may also like these products", "upsell_checkout_btn": "Checkout", "share": "Share product", "share_on_facebook": "Share on Facebook", "share_on_twitter": "Share on Twitter", "share_on_pinterest": "Share on Pinterest", "share_on_google": "Share on Google+", "share_on_linkedin": "Share on LinkedIn", "availability": "Availability", "in_stock": "In Stock", "out_of_stock": "Out of stock", "quick_overview": "Quick Overview", "details": "Details", "reviews": "Reviews", "first_review": "Be the first review", "tags": "Product Tags", "size_chart": "Size Chart", "options": "Options", "vendor": "Vendor", "features": "Features", "sale_left_text": "[[ sales ]] SOLD. HURRY! ONLY A FEW LEFT!", "checkout_text": "Secured and trusted checkout with" }, "upsell": { "recommend_text": "Someone purchased a", "minute_ago": "minutes ago" } }, "gift_cards": { "issued": { "title_html": "Here's your [[ value ]] gift card for [[ shop ]]!", "subtext": "Your gift card", "disabled": "Disabled", "expired": "Expired on [[ expiry ]]", "active": "Expires on [[ expiry ]]", "redeem_html": "Use this code at checkout to redeem your [[ value ]] gift card", "shop_link": "Start shopping", "print": "Print this gift card", "remaining_html": "[[ balance ]] left", "add_to_apple_wallet": "Add to Apple Wallet" } }, "date_formats": { "month_day_year": "%B %d, %Y" } } }