Arduino Activity 6: Buzzer

Arduino Activity 6: Buzzer

by ACROBOTIC Industries


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

In this activity we’ll generate different tones with a microcontroller and control their volume. We’ll also learn about some Arduino IDE functions, particularly those used to handle analog values.

List of Materials

  • 1 x Arduino Uno R3
  • 1 x USB-A to USB-B Male / Male Cable
  • 1 x 1KOhm Potentiometer
  • 1 x 10KOhm Potentiometer
  • 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 a program to our Arduino Uno board, it's available in our Github repository:

We can open a new window in the Arduino environment and copy-paste the code.

Digital Signals: Frequency vs. Duty Cycle (PWM)

In the context of embedded electronics, digital signals are electrical signals comprised by changes in voltage between two or more discrete values.  These changes can occur either as a function of time, most commonly as a train of pulses.  They are often used to transmit data either by representing a bitstream (e.g., serial communication), encoding analog values (e.g., Pulse-Code Modulation), and can even be used for digital modulation of an analog signal.

Digital Signals as Rectangular Waves

When digital signals behave as a pulse train, they're represented as a particular function of time called rectangular waves.  Thus, they are characterized by a duty cycle and a frequency.  Within a single period of the signal, the duty cycle is defined as the ratio between the time the signal has a high value over the total time duration of the period. Similarly, the signal's frequency is defined as one over the total time duration of the period. 

Frequency and Duty Cycle

By changing these two parameters, we will modify both the pitch (controlled by frequency) and volume (controlled by duty cycle) of the tones played through the speaker.

Generating Sound: Transducers vs. Buzzers

In order to turn electrical signals into sound we'll make use of a transducer.  In a general sense, a transducer is defined as any device that converts variations of any physical quantity into an electrical signal or viceversa.  The particular transducer we've chosen is a little Piezo Transducer (sometimes called Piezo Diaphragm), which contains a disk made out of piezoceramic, a material that exhibits an inverse piezo electric effect—turning electrical signals into mechanical pressure.

Piezoceramic Disc Inside a Piezo Transducer

When we apply a voltage to a Piezo Transducer, the piezoceramic disk moves and changes the pressure of air molecules around it, effectively generating a sound.  This sound is audible (to our ears) and resembles a "click".  By generating a digital signal with a microcontroller connected to the Piezeo Transducer in the audible frequencies, 20Hz to 20KHz, we can make it generate tones with different pitches.

Piezo Sounder Teardown

Piezo Transducers are often confused with Piezo Sounders or Piezo Buzzers (the terms are used interchangeably!).  Although the inverse piezo electric effect is similar in the two components, Piezo Sounders and Buzzers contain built-in oscillator circuitry to produce a single-frequency sound when a voltage is applied (e.g., the beeping sound when a truck is backing up).

Variable Resitors and Potentiometers

A potentiometer is simply a variable resistor that, unlike a regular resistor, has three terminals (pins). The resistance between the two pins at each end is fixed, whereas the resistance between the middle pin and either of the other two varies.  As shown by the digram below, the change in resistance affects the path through which the current travels when a voltage is applied to 2 of the pins. 

How a Potentiometer Works

Similar to a regular resistor, potentiometers have a fixed resistance value (in this case 1KOhm).  If we measure the resistance of this device by connecting a multimeter to the two pins furthest apart, we can read this reasistance value maximum value every time.

So what's the use of the middle pin of a potentiometer?

The middle pin of a potentiometer is internally connected to a little wiper.  The wiper is also connected to the knob (or sometimes a screw depending on the potentiometer model) on top of the potentiometer.  As we turn the knob, the wiper changes the point of contact with the resistive material inside.  This change in the wiper's position physically alters the amount of resistive material between the middle pin and each of the other two pins, one becomes smaller while the other becomes larger.  If we continue moving the wiper all the way to the end, the middle pin will be internally connected to one of the two other pins, and the amount of resistive material between those two pins and the third one will effectively be 1KOhm.

We will be using the varying resistance of the potentiometer to adjust the Voltage read by the microcontroller using a Voltage Divider circuit.  We'll look at Voltage Dividers in more detail in Arduino Activity 8. Photoresistors.

Wiring: Analog Input and Volume

After learning a about transducers, buzzers, and potentiometers we proceed to connect the first circuit.  As always, it's important to disconnect the Arduino board from any power source including the USB port from our computer.  This allows us to catch any wiring mistakes before turning it on, preventing components from being damaged.  

For this circuit we will need a Piezoelectric Transducer, a 1KOhm Trimpot (potentiometer), and 1 resistor (330Ohm).  We follow the diagram below to wire up the circuit:

Wiring: Analog Input and Frequency

Please note that the transducer is sensitive to polarity, so we must connect the terminal marked with the positive (+) symbol to pin 11 (either directly or using the breadboard as shown).  

Code Walkthrough: Analog Input and Volume

After ensuring that our connections are correct, we can plug in the USB cable to both the Arduino and the computer.  After uploading the Analog Input and Volume program, we'll notice that by moving the knob we can increase or decrease the volume of a fixed-frequency tone.  Let's have a look over the code used to do this:

Inside our setup() function we need only initialize the communication over serial, by calling the method begin() from the available Serial object.  If you find the terminology confusing, have a look at our Classes and Object-Oriented Programming tutorial.  We'll be using the Serial object later in the code to communicate data read by the microcontroller on the Arduino board.

  // initialize serial communications at 9600 bps:

Moving to our loop() function, we start by using the analogRead() function to read the voltage at the pin (A0), that is, where the potentiometer's middle pin is connected.

  // read the analog in value:
  sensor_value = analogRead(analog_in_pin); 

The variable sensor_value stores the value returned by the analogRead() function, which is in the range 0 to 1023.  When the voltage at the pin is 0V, the value read is 0.  When the voltage at the pin is 5V, which is the maximum voltage that a pin on an Arduino Uno board can read, then the value is 1023.  This is because the reading takes place through a 10-bit Analog-To-Digital Converter (ADC).  We want to use this input to control the volume of the speaker by adjusting the duty cycle of the PWM output signal.  

As seen in the video below, under a constant frequency, increasing the duration of Tmax results in a higher average voltage for the entire signal.  A higher voltage means that the piezo is driven with more (electric) power, which is why it is able to generate a louder sound.

As we've seen in previous tutorials, we can change the PWM signal's duty cycle with the analogWrite() function.  Using a value from 0 to 255 we can adjust it from 0 (always OFF or 0% duty cycle) to 255 (always ON or 100% duty cycle).  Because sensor_value ranges between 0 to 1023, we need to scale down first.  Moreover, we wouldn't want 100% duty cycle because an always ON signal would not generate any vibration of the piezo tranducer.  In fact, we don't gain anything by having the duty cycle above 50% as (in theory) both the OFF and ON periods of the signal are important for vibrating the piezo transducer effectively.  This is a good rule of thumb, but in practice there are different factors involved (see the Code Tinkering section) that'll affect the vibration.

Instead of doing the calculations by hand, we make use of the available map() function.  It requires five arguments to specify the scaling we want done: map(variable, current_min, current_max, new_min, new_max). Using those values, it performs the scaling of variable by way of interpolation from the range current_min to current_max to the range new_min to new_max. Looking at our code we see the following:

  // map it to the range of the analog out:
  volume = map(sensor_value, 0, 1023, 0, 127);

This means that when sensor_value is 0, volume should be 0, and when sensor_value is 1023, volume should be 127.  We then use volume as the value that we want to write with the analogWrite() function.

  // change the analog out value:
  analogWrite(analog_out_pin, volume);

This is why the volume of the speaker gets louder and softer as we turn the knob. The Arduino reads the voltage coming from the potentiometer, converts it to a number from 0 to 1023. Then it maps this value to a value from 0 to 127, and assigns the value as the duty cycle of the PWM signal on the output pin.

If we open the Serial Monitor by clicking on the square button with a magnifying glass (top-right of the window) see the values being sent from the microcontroller to the computer over USB.  We use the print() and println() methods of the Serial object for this purpose:

  // print the results to the serial monitor:
  Serial.print("sensor = " );                       
  Serial.print("\t output = ");      

The output of the Serial Monitor should look like this: 

Serial Monitor Output

Code Walkthrough: Analog Input and Frequency

Without changing the circuitry, we can now upload the Analog Input and Frequency program.  After doing so, we can see how now turning the knob will change the pitch of the tone while the volume remains constant. Since we're reusing the circuit to run with this program, and we know that our previous code didn't damage our electronics, we leave the connections where they are without any trouble.

The code is almost identical to our previous program.  The main difference is inside the loop() function.  We rename the variable that holds the output of the map() function for frequency (instead of volume), and we also change the range of the output to be between 120 to 1500.  This is because instead of our usual function call to analogWrite(), we'll make use of the function tone().  

The tone() function changes the frequency of the same rectangular wave signal we were using earlier while keeping the frequency constant.  That is, it changes the total Period (Tmin+Tmax) of the signal rather than only the ON (OFF) duration Tmax (Tmin).  At it's minimum of 120, the output signal is switching on and off 120 times in one second, and at its maximum value of 1500, the output signal is switching 1500 times per second.   These frequencies may seem arbitrary, but we're choosing them based on the range of human hearing which is between 20 and 20,000Hz!

  frequency = map(sensor_value, 0, 1023, 120, 1500);    
  // change the analog out value:
  tone(analog_out_pin, frequency); 

Just as before, when we turn the knob we change the value read by the microcontroller at pin A0, this varies the value passed to the map() function, which in turn changes the frequency passed to the tone() function. We hear the change in the frequency at which the piezo transducer is being driven ON and OFF!


Can't hear sound!

A few seconds after uploading the program Arduino board, you will begin to hear an annoying tone coming from the speaker. If you do not hear anything, try turning the knob all the way in both directions until you hear a sound. If after this you still can not hear a tone, verify that your speaker is connected with the correct polarity. If the speaker is connected in the correct polarity, verify all other connections.

Serial Monitor display woes.

If your Serial Monitor is displaying gibberish, check the number labeled "baud" on the bottom right corner of the window, and make sure this is the same number as the Serial.begin(####) in our code.

If your Serial Monitor doesn't seem to be keeping up with the chaning values of the potentiometer, make sure the Autoscroll option is checked at the bottom left corner of the window.

Hardware Tinkering

We didn't go into too much detail about analog-to-digital conversion.  As a relevant exercise, experiment with substituting the 1KOhm Potentiometer for the 10K one.

Code Tinkering

We learned that by adjusting the duty cycle of the PWM signal with a fixed frequency affects the amplitude (or 'strength') with which the piezo transducer vibrates.  However, the vibration amplitude as a function of ON/OFF-time is extremely nonlinear.  See for yourself by changing the range to the full 0 to 255.  The volume goes louder even when we think it should be softer due to resonance, and other electrical and mechanical phenomena. 

If we change both the duty cycle and the frequency of the rectangular wave signal, we should be able to change both the volume and pitch of the sound generated.  However, neither the tone() library nor the analogWrite() function have a way of changing both parameters simultaneously.  Have a look at the wonderful codebase developed for the Teensy development board, and have a crack at porting it over to your Arduino!

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" } } }