# Using Piezo Buzzers with CircuitPython & Arduino

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/049/306/medium800/circuitpython_IMG_5912.jpg?1513332842)

Piezo buzzers are simple devices that can generate basic beeps and tones. &nbsp;They work by using a piezo crystal, a special material that changes shape when voltage is applied to it. &nbsp;If the crystal pushes against a diaphragm, like a tiny speaker cone, it can generate a pressure wave which the human ear picks up as sound. &nbsp;Simple change the frequency of the voltage sent to the piezo and it will start generating sounds by changing shape very quickly!

This guide will explore how to generate tones with a piezo from CircuitPython or Arduino code.&nbsp;

With CircuitPython, you can use simple Python code to play beeps and music notes with the piezo.&nbsp; You can even use the CircuitPython REPL to make sound interactively!

In addition this guide will also show basic piezo control with Arduino code too, so you can use it for either!

# Using Piezo Buzzers with CircuitPython & Arduino

## Hardware

To follow this guide you'll need the following parts:

- **A piezo buzzer. &nbsp;** Piezo buzzers are like tiny little speakers, but unlike speakers they don't require an amplifier or other complex circuitry to drive them (consequently they aren't nearly as loud as a speaker and amplifier either!). &nbsp;When voltage is applied to the piezo it grows and shrinks in size, and by changing the voltage over time you can make the piezo change shape fast enough to create a pressure wave that your ears interpret as sound.
- **A board running CircuitPython or Arduino.** &nbsp; If you're controlling piezos from CircuitPython you'll need a board like the [Feather M0 basic](https://www.adafruit.com/product/2772) which can be loaded with CircuitPython firmware.&nbsp; This guide will also show basic piezo code for Arduino too.
- [**Breadboard**](https://www.adafruit.com/product/65) **and [jumper wires](https://www.adafruit.com/product/153).**&nbsp; You'll need these parts to connect components to your development board.

# Wiring

To connect a piezo buzzer you just need to connect one leg of the buzzer to your board ground, and another leg to a PWM-capable or analog-out output of your board. &nbsp;For the Feather M0 and other M0 boards look for a squiggly line next to a pin to denote that it supports PWM output. &nbsp;For other boards check the guide or documentation to see which pins support PWM output.

Arduino uses an interrupt system for piezos, so you can use _any_ pin.

For example here's how to wire a piezo to a Feather M0:

![](https://cdn-learn.adafruit.com/assets/assets/000/049/304/medium800/circuitpython_m0_piezo_bb.png?1513294087)

- **One leg of the piezo buzzer** (or black wire) to **board GND**.
- **The other leg of the piezo buzzer** (or red wire) to **board D5** (or any other PWM-capable output).

# Using Piezo Buzzers with CircuitPython & Arduino

## CircuitPython

To control the piezo from CircuitPython we'll use its built in PWM, or pulse-width modulation, signal generation capabilities.&nbsp; Be sure to read the [CircuitPython analog I/O guide](../../../../circuitpython-basics-analog-inputs-and-outputs/analog-signals) for more details on PWM signals!

Before continuing make sure your hardware is wired up as shown on the previous page.

Next make sure you are running the&nbsp;[latest version of Adafruit CircuitPython](../../../../welcome-to-circuitpython/installing-circuitpython)&nbsp;for your board, then&nbsp;[connect to the board's serial REPL&nbsp;](../../../../welcome-to-circuitpython/the-repl)so you are at the CircuitPython&nbsp; **\>\>\>** &nbsp;prompt.

# Setup

First you need to import a few modules to access the PWM output capabilities of CircuitPython:

```auto
import board
import pwmio
```

Now you can create a PWM signal output that will drive the buzzer to make sound:

```auto
buzzer = pwmio.PWMOut(board.D5, variable_frequency=True)
```

There are a couple important things happening with the line above.&nbsp; This is an initializer which is creating an instance of the PWMOut class and part of that initialization process is specifying these two values:

- **The pin that will be the PWM output.** &nbsp; In this case it's pin D5 on the development board.&nbsp; If you're using a different output be sure to specify the right pin name here (and make sure the pin supports PWM output as mentioned on the previous page!).
- **The variable\_frequency boolean is True.** &nbsp; This is an optional value that we're specifying as a keyword argument to tell the PWM output that we want to be able to change its frequency, or how often the signal changes. &nbsp;By default PWM outputs in CircuitPython have a fixed frequency, but if this special keyword is specified you can instead change the frequency of the output.

# Making Tones with PWM

Now we can generate tones using the PWM output. &nbsp;Remember from the [CircuitPython analog I/O guide PWM page](../../../../circuitpython-basics-analog-inputs-and-outputs/pulse-width-modulation-outputs) a PWM signal is just a fast on/off signal, i.e. a square wave. &nbsp;When a square wave modulates the movement of something, like a buzzer, it generates a pressure wave that the human ear interprets as sound. &nbsp;By changing the frequency, or how often the square wave changes from high to low, you can change the frequency of the tone that you'll hear.

Changing the frequency of the PWM output is easy, just modify the frequency attribute to set a new value in hertz. &nbsp;For example a 440 hz wave is the same pitch as an A4 note in music:

```auto
buzzer.frequency = 440
```

You might notice after setting the frequency above nothing actually happened--no sound is being made by the buzzer. &nbsp;Is the buzzer broken? &nbsp;Nope! &nbsp;There's one more thing you need to do to create the square wave signal, you need to set the duty cycle of the PWM output.

Like the [CircuitPython analog I/O PWM page mentions](../../../../circuitpython-basics-analog-inputs-and-outputs/pulse-width-modulation-outputs) the duty cycle of a signal is the percent of time that it's high vs. low. &nbsp;We want to generate a square wave which is high and low for exactly the same amount of time (i.e. 50% duty cycle). &nbsp;This will generate a square wave of the previously specified frequency on the PWM output, and as a result induce a pressure wave from the buzzer that you'll hear as sound.

To simplify turning on and off the buzzer let's make a couple variables to represent the 0% and 50% duty cycle values that turn the buzzer off and on respectively:

```auto
OFF = 0
ON = 2**15
```

The **ON** value is 2^15, or 32768, which is about half of the maximum duty cycle value (65535).

Now set the buzzer duty cycle to **ON** to start playing the tone at the previously set frequency:

```auto
buzzer.duty_cycle = ON
```

You should hear the buzzer start to play a tone at 440 hz!

To stop the tone playback change the duty cycle to **OFF** or 0%:

```auto
buzzer.duty_cycle = OFF
```

Now the buzzer stops making sound!

You can change the frequency at any time too, whether the buzzer is playing sound or not. &nbsp;Here are some interesting frequency values to try (they're the frequencies for musical notes):

- 262 hz, C4
- 294 hz, D4
- 330 hz, E4
- 349 hz, F4
- 392 hz, G4
- 440 hz, A4
- 494 hz B4

Try turning the buzzer on and changing the frequency between a few note values:

```auto
buzzer.duty_cycle = ON
buzzer.frequency = 262 # C4
buzzer.frequency = 294 # D4
buzzer.frequency = 330 # E4
buzzer.duty_cycle = OFF
```

That's all there is to simple tone playback with a piezo buzzer and CircuitPython's built-in PWM output!

Here's a complete example that will play a scale of tones up and down repeatedly. &nbsp;Save this as **main.py** on your board and be ready after saving it as the music playback will immediately start:

```auto
import time

import board
import pwmio


# Define a list of tones/music notes to play.
TONE_FREQ = [ 262,  # C4
              294,  # D4
              330,  # E4
              349,  # F4
              392,  # G4
              440,  # A4
              494 ] # B4

# Create piezo buzzer PWM output.
buzzer = pulseio.PWMOut(board.D5, variable_frequency=True)

# Start at the first note and start making sound.
buzzer.frequency = TONE_FREQ[0]
buzzer.duty_cycle = 2**15  # 32768 value is 50% duty cycle, a square wave.

# Main loop will go through each tone in order up and down.
while True:
    # Play tones going from start to end of list.
    for i in range(len(TONE_FREQ)):
        buzzer.frequency = TONE_FREQ[i]
        time.sleep(0.5)  # Half second delay.
    # Then play tones going from end to start of list.
    for i in range(len(TONE_FREQ)-1, -1, -1):
        buzzer.frequency = TONE_FREQ[i]
        time.sleep(0.5)
```

# Making Tones With SimpleIO

Another option to generate a tone is with the [SimpleIO module](https://github.com/adafruit/Adafruit_CircuitPython_SimpleIO) for CircuitPython.&nbsp; This module simplifies tone generation by doing all the PWM duty cycle and frequency logic for you automatically.&nbsp; With a simple tone function call you can play a tone for a period of time--no setup or duty cycle calculation necessary!&nbsp; You might find this approach easier to start with for basic tone playback compared to the PWM approach shown above.

To follow this approach you'll need to install the&nbsp;[Adafruit CircuitPython SimpleIO](https://github.com/adafruit/Adafruit_CircuitPython_SimpleIO)&nbsp;library on your CircuitPython board.&nbsp;&nbsp;

First make sure you are running the&nbsp;[latest version of Adafruit CircuitPython](../../../../welcome-to-circuitpython/installing-circuitpython)&nbsp;for your board.

Next you'll need to install the necessary libraries&nbsp;to use the hardware--carefully follow the steps to find and install these libraries from&nbsp;[Adafruit's CircuitPython library bundle](https://github.com/adafruit/Adafruit_CircuitPython_Bundle).&nbsp; Our introduction guide has&nbsp;[a great page on how to install the library bundle](../../../../welcome-to-circuitpython/circuitpython-libraries)&nbsp;for both express and non-express boards.

Remember for non-express boards like the, you'll need to manually install the necessary libraries from the bundle:

- **simpleio.mpy**

You can also download the&nbsp; **simpleio.mpy** &nbsp;from&nbsp;[its releases page on Github](https://github.com/adafruit/Adafruit_CircuitPython_SimpleIO/releases).

Before continuing make sure your board's lib folder or root filesystem has the **simpleio.mpy&nbsp;** file copied over.

Next&nbsp;[connect to the board's serial REPL&nbsp;](../../../../welcome-to-circuitpython/the-repl)so you are at the CircuitPython&nbsp; **\>\>\>** &nbsp;prompt.&nbsp; Then import the **board** and **simpleio** modules:

```auto
import board
import simpleio
```

Now you'e ready to use the tone function in SimpleIO to play a tone on a pin connected to a piezo buzzer.&nbsp; Try the following to play a 440 hz tone for 1 second:

```auto
    simpleio.tone(board.D5, 440, duration=1.0)
  
```

You should hear a 440 hz tone, or an A4 note, played for one second.&nbsp; The parameters you pass to the tone function control the frequency and duration of the tone:

- The first parameter is the pin connected to the buzzer or speaker, in this case digital pin 5 as shown in the wiring for this guide.
- The second parameter is the frequency in Hz of the tone to play back. This can be a floating point but note that at higher frequencies (\> 10KHz) the precision may not match perfectly
- The last parameter is a keyword **duration** which specifies how long to play the tone in seconds.&nbsp; By default if you don't provide a value here the tone will be played for one second, however you can specify shorter or longer values.

Another example is playing a 400 hz tone for 3 seconds:

```auto
simpleio.tone(board.D5, 400, duration=3.0)
```

Notice how the frequency and duration parameters changed to specify these different values!

That's all there is to basic tone playback on a piezo with the SimpleIO module!&nbsp; Here's another complete example that plays a scale of notes using SimpleIO's tone function.&nbsp; Again save this as a **main.py** on your board to have it run:

```auto
import board

import simpleio


# Define pin connected to piezo buzzer.
PIEZO_PIN = board.D5

# Define a list of tones/music notes to play.
TONE_FREQ = [ 262,  # C4
              294,  # D4
              330,  # E4
              349,  # F4
              392,  # G4
              440,  # A4
              494 ] # B4


# Main loop will go through each tone in order up and down.
while True:
    # Play tones going from start to end of list.
    for i in range(len(TONE_FREQ)):
        simpleio.tone(PIEZO_PIN, TONE_FREQ[i], duration=0.5)
    # Then play tones going from end to start of list.
    for i in range(len(TONE_FREQ)-1, -1, -1):
        simpleio.tone(PIEZO_PIN, TONE_FREQ[i], duration=0.5)
```

# Using Piezo Buzzers with CircuitPython & Arduino

## Arduino

You can also control a piezo buzzer from Arduino in a similar way as CircuitPython with Arduino's [tone function](https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/).&nbsp; There are actually quite a few resources and guides for using Arduino to play tones on a piezo, so this page will just highlight how to use a servo in Arduino in the same way as with CircuitPython from the previous page.&nbsp; For more exploration of piezo and Arduino be sure to check out the entire [Arduino Lesson 10: Making Sounds](../../../../adafruit-arduino-lesson-10-making-sounds).

First make sure your piezo is wired to your board exactly as shown on the hardware page of this guide.&nbsp; You'll also need the Arduino IDE installed and configured to upload to your board.&nbsp; Remember Arduino sketches have to be written entirely up front and uploaded to the board--you can't interactively control servos like you can with CircuitPython.

With Arduino you use the [tone](https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/) function to play a 50% duty cycle (i.e. square wave) on any digital output. &nbsp;The function needs to be told the pin and frequency of the tone as one of the parameters and will immediately start playback of the tone/signal. &nbsp;To stop playback you just call the [noTone](https://www.arduino.cc/reference/en/language/functions/advanced-io/notone/) function (providing only the pin).

Here's a complete Arduino sketch that uses the tone function to play a scale of notes just like the CircuitPython example on the previous page. &nbsp;Upload this to your board:

```auto
#define PIEZO_PIN  5      // Pin connected to the piezo buzzer.

// Define list of tone frequencies to play.
int toneFreq[] = { 262,   // C4
                   294,   // D4
                   330,   // E4
                   349,   // F4
                   392,   // G4
                   440,   // A4
                   494 }; // B4
int toneCount = sizeof(toneFreq)/sizeof(int);

void setup() {
  // No setup necessary!
}

void loop() {
  // Loop up through all the tones from start to finish.
  for (int i=0; i < toneCount; ++i) {
    tone(PIEZO_PIN, toneFreq[i]);
    delay(500);  // Pause for half a second.
  }
  // Loop down through all the tones from finish to start again.
  for (int i=toneCount-1; i >= 0; --i) {
    tone(PIEZO_PIN, toneFreq[i]);
    delay(500);
  }
  // Remember you can stop tone playback with the noTone function:
  // noTone(PIEZO_PIN);
}
```

After uploading you should hear the piezo play back each tone in sequence up and down. &nbsp;That's all there is to using a piezo buzzer with Arduino to play tones!


## Featured Products

### Piezo Buzzer

[Piezo Buzzer](https://www.adafruit.com/product/160)
Piezo buzzers are used for making beeps, tones and alerts. This one is petite but loud! Drive it with 3-30V peak-to-peak square wave. To use, connect one pin to ground (either one) and the other pin to a square wave out from a timer or microcontroller. For the loudest tones, stay around 4 KHz,...

In Stock
[Buy Now](https://www.adafruit.com/product/160)
[Related Guides to the Product](https://learn.adafruit.com/products/160/guides)
### Large Enclosed Piezo Element w/Wires

[Large Enclosed Piezo Element w/Wires](https://www.adafruit.com/product/1739)
This large (30mm diameter) piezo element is nicely enclosed with mounting holes so you can attach easily. Piezo elements convert vibration to voltage or voltage to vibration. That means you can use this as a buzzer for making beeps, tones and alerts AND you can use it as a sensor, to detect...

In Stock
[Buy Now](https://www.adafruit.com/product/1739)
[Related Guides to the Product](https://learn.adafruit.com/products/1739/guides)
### Small Enclosed Piezo w/Wires

[Small Enclosed Piezo w/Wires](https://www.adafruit.com/product/1740)
This small (14mm diameter) piezo element is nicely enclosed so you can attach easily. Piezo elements convert vibration to voltage or voltage to vibration. That means you can use this as a buzzer for making beeps, tones, and alerts, AND you can use it as a sensor to detect fast movements like...

In Stock
[Buy Now](https://www.adafruit.com/product/1740)
[Related Guides to the Product](https://learn.adafruit.com/products/1740/guides)
### Adafruit Feather M0 Basic Proto - ATSAMD21 Cortex M0

[Adafruit Feather M0 Basic Proto - ATSAMD21 Cortex M0](https://www.adafruit.com/product/2772)
Feather is the new development board from Adafruit, and like its namesake it is thin, light, and lets you fly! We designed Feather to be a new standard for portable microcontroller cores.

This is the&nbsp; **Feather M0 Basic Proto** ,&nbsp;it has a bunch of prototyping space...

In Stock
[Buy Now](https://www.adafruit.com/product/2772)
[Related Guides to the Product](https://learn.adafruit.com/products/2772/guides)
### Adafruit Feather M0 Express

[Adafruit Feather M0 Express](https://www.adafruit.com/product/3403)
At the Feather M0's heart is an ATSAMD21G18 ARM Cortex M0+ processor, clocked at 48 MHz and at 3.3V logic, the same one used in the new&nbsp;[Arduino Zero](https://www.adafruit.com/products/2843). This chip has a whopping 256K of FLASH (8x more than the Atmega328 or 32u4) and...

In Stock
[Buy Now](https://www.adafruit.com/product/3403)
[Related Guides to the Product](https://learn.adafruit.com/products/3403/guides)
### Adafruit METRO M0 Express - designed for CircuitPython

[Adafruit METRO M0 Express - designed for CircuitPython](https://www.adafruit.com/product/3505)
Metro is our series of microcontroller boards for use with the Arduino IDE. This new **Metro M0 Express** board looks a whole lot like our&nbsp;[original Metro 328](https://www.adafruit.com/product/2488), but with a huge upgrade. Instead of the ATmega328, this Metro...

In Stock
[Buy Now](https://www.adafruit.com/product/3505)
[Related Guides to the Product](https://learn.adafruit.com/products/3505/guides)
### Adafruit Trinket M0 - for use with CircuitPython & Arduino IDE

[Adafruit Trinket M0 - for use with CircuitPython & Arduino IDE](https://www.adafruit.com/product/3500)
The&nbsp;Adafruit Trinket M0 may be small, but do not be fooled by its size! It's a tiny microcontroller board, built around the Atmel ATSAMD21, a little chip with _a lot_ of power. We wanted to design a microcontroller board that was small enough to fit into any project, and low...

Out of Stock
[Buy Now](https://www.adafruit.com/product/3500)
[Related Guides to the Product](https://learn.adafruit.com/products/3500/guides)
### Adafruit GEMMA M0 - Miniature wearable electronic platform

[Adafruit GEMMA M0 - Miniature wearable electronic platform](https://www.adafruit.com/product/3501)
The **Adafruit Gemma M0** is a super small microcontroller board, with just enough built-in to create many simple projects. It may look small and cute: round, about the size of a quarter, with friendly alligator-clip sew pads. But do not be fooled! The Gemma M0 is incredibly...

In Stock
[Buy Now](https://www.adafruit.com/product/3501)
[Related Guides to the Product](https://learn.adafruit.com/products/3501/guides)

## Related Guides

- [Adafruit Feather M0 Express](https://learn.adafruit.com/adafruit-feather-m0-express-designed-for-circuit-python-circuitpython.md)
- [Adafruit Metro M0 Express](https://learn.adafruit.com/adafruit-metro-m0-express.md)
- [Adafruit Trinket M0](https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino.md)
- [Adafruit Circuit Playground Express](https://learn.adafruit.com/adafruit-circuit-playground-express.md)
- [CircuitPython Hardware: Charlieplex LED Matrix](https://learn.adafruit.com/micropython-hardware-charlieplex-led-matrix.md)
- [Crickit Powered Minerva Owl Robot](https://learn.adafruit.com/crickit-powered-owl-robot.md)
- [Using Circuit Playground Express, MakeCode and CircuitPython on a Chromebook](https://learn.adafruit.com/using-circuit-playground-express-makecode-circuitpython-on-a-chromebook.md)
- [NeoPixel Spats with Gemma and MakeCode](https://learn.adafruit.com/neopixel-spats.md)
- [What is Web MIDI & BLE MIDI?](https://learn.adafruit.com/web-ble-midi.md)
- [USB Foot Switch Controller in CircuitPython](https://learn.adafruit.com/usb-foot-switch-circuit-python.md)
- [Chirping Plush Owl Toy](https://learn.adafruit.com/chirping-plush-owl-toy.md)
- [CircuitPython 101: Basic Builtin Data Structures](https://learn.adafruit.com/basic-datastructures-in-circuitpython.md)
- [Circuit Playground Seashell Pendant](https://learn.adafruit.com/circuit-playground-seashell-pendant.md)
- [Trinket / Gemma Mini-Theremin](https://learn.adafruit.com/trinket-gemma-mini-theramin-music-maker.md)
- [Using Servos With CircuitPython and Arduino](https://learn.adafruit.com/using-servos-with-circuitpython.md)
- [Circuit Playground D6 Dice](https://learn.adafruit.com/circuit-playground-d6-dice.md)
- [Adafruit Feather M0 Basic Proto](https://learn.adafruit.com/adafruit-feather-m0-basic-proto.md)
- [Debugging the SAMD21 with GDB](https://learn.adafruit.com/debugging-the-samd21-with-gdb.md)
- [Digital Fidget Spinner](https://learn.adafruit.com/digital-fidget-spinner.md)
