|
| 1 | +{ |
| 2 | + "cells": [ |
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "id": "f3918b49-9476-4415-a7e9-68539c202181", |
| 6 | + "metadata": {}, |
| 7 | + "source": [ |
| 8 | + "# Project 2 - Circuit 2A: Buzzer\n", |
| 9 | + "\n", |
| 10 | + "In this circuit, you'll use the RedBoard and a small buzzer to make music, and you'll learn how to program your own songs using lists.\n", |
| 11 | + "\n", |
| 12 | + "\n", |
| 13 | + "\n", |
| 14 | + "## New Components\n", |
| 15 | + "\n", |
| 16 | + "### Buzzer\n", |
| 17 | + "\n", |
| 18 | + "The buzzer uses a small magnetic coil to vibrate a metal disc inside a plastic housing. By pulsing electricity through the coil at different rates, different frequencies (pitches) of sound can be produced. Attaching a potentiometer to the output allows you to limit the amount of current moving through the buzzer and lower its volume.\n", |
| 19 | + "\n", |
| 20 | + "\n", |
| 21 | + "\n", |
| 22 | + "## New Concepts\n", |
| 23 | + "\n", |
| 24 | + "### Reset Button\n", |
| 25 | + "\n", |
| 26 | + "The RedBoard has a built-in reset button. This button will reset the board and start the code over from the beginning, running what is in setup() and then loop().\n", |
| 27 | + "\n", |
| 28 | + "TODO: Swap out with RP2350 photo\n", |
| 29 | + "\n", |
| 30 | + "\n", |
| 31 | + "\n", |
| 32 | + "### Playing Sound with PWM\n", |
| 33 | + "To control the buzzer, we will use the same `PWM` functionality that we used to control the RGB LEDs. By passing different frequencies and durations to our PWM we can play different tones for different lengths of time from our buzzer.\n", |
| 34 | + "\n", |
| 35 | + "### Lists\n", |
| 36 | + "[Lists](https://docs.python.org/3/tutorial/introduction.html#lists) are used like variables, but they can store multiple values. Imagine that you want to store the frequency for each note of the C major scale. We could make seven variables and assign a frequency to each one, or we could use an list and store all seven in the same list, as shown below. To refer to a specific value in the list, an index number is used. lists are indexed from 0. For example, to call the first element in the list, use `list_name[0]` to call the second element, `use list_name[1]` and so on.\n", |
| 37 | + "\n", |
| 38 | + "| Musical Note | Frequency (Hz) | Using Variables | Using an Array |\n", |
| 39 | + "|--------------|---------------|----------------|------------------|\n", |
| 40 | + "| A | 220 | aFrequency | frequency[0] |\n", |
| 41 | + "| B | 247 | bFrequency | frequency[1] |\n", |
| 42 | + "| C | 261 | cFrequency | frequency[2] |\n", |
| 43 | + "| D | 294 | dFrequency | frequency[3] |\n", |
| 44 | + "| E | 330 | eFrequency | frequency[4] |\n", |
| 45 | + "| F | 349 | fFrequency | frequency[5] |\n", |
| 46 | + "| G | 392 | gFrequency | frequency[6] |\n", |
| 47 | + "\n", |
| 48 | + "### `len()` function\n", |
| 49 | + "To get the length of a list (and many other types of objects in python) you can call `len()` on it. For example, to get the length of a list called `myList` we could use: `len(myList)` and the length would be returned. This is helpful when searching through all of the elements of a list.\n", |
| 50 | + "\n", |
| 51 | + "## Hardware Hookup\n", |
| 52 | + " ⚠️ **Warning For Polarized Components**: Pay special attention to the component’s markings indicating how to place it on the breadboard. Polarized components can only be connected to a circuit in one direction.\n", |
| 53 | + "\n", |
| 54 | + "The buzzer is polarized. To see which leg is positive and which is negative, flip the buzzer over and look at the markings underneath. Keep track of which pin is where, as they will be hard to see once inserted into the breadboard. There is also text on the positive side of the buzzer, along with a tiny (+) symbol.\n", |
| 55 | + "\n", |
| 56 | + "\n", |
| 57 | + "\n", |
| 58 | + "\n", |
| 59 | + "### Volume Knob\n", |
| 60 | + "All of the circuits in Project 2 make use of a potentiometer as a rudimentary volume knob. Notice that only two of the potentiometer's legs are used in these circuits. In these instances, the potentiometer is acting as a variable resistor, limiting the amount of current flowing to the speaker and thus affecting the volume as you turn the knob. This is similar to the current-limiting resistor used to limit current to the LED in circuit 1A --- only this time the resistance is variable.\n", |
| 61 | + "\n", |
| 62 | + "Ready to start hooking everything up? Check out the circuit diagram and hookup table below to see how everything is connected.\n", |
| 63 | + "\n", |
| 64 | + "## Circuit Diagram\n", |
| 65 | + "\n", |
| 66 | + "TODO: Replace with RP2350...\n", |
| 67 | + "\n", |
| 68 | + "\n", |
| 69 | + "\n", |
| 70 | + "**Note for Advanced Users**: If you know how to read datasheets and schematics, you can also refer to the schematic below as an alternative.\n", |
| 71 | + "\n", |
| 72 | + "\n", |
| 73 | + "\n", |
| 74 | + "## Hookup Table\n", |
| 75 | + "\n", |
| 76 | + "\n", |
| 77 | + "| Component | RedBoard | Breadboard | Breadboard | Breadboard |\n", |
| 78 | + "|-----------------|------------------|-----------------|-----------------|-----------------|\n", |
| 79 | + "| Buzzer | | J1 (Buzzer +) | J3 (Buzzer -) | |\n", |
| 80 | + "| Potentiometer | | B1 | B2 | B3 |\n", |
| 81 | + "| Jumper Wire | GND | GND Rail ( - ) | | |\n", |
| 82 | + "| Jumper Wire | Digital Pin 34 | F1 | | |\n", |
| 83 | + "| Jumper Wire | | E2 | GND Rail ( - ) | |\n", |
| 84 | + "| Jumper Wire | | E1 | F3 | |\n" |
| 85 | + ] |
| 86 | + }, |
| 87 | + { |
| 88 | + "cell_type": "markdown", |
| 89 | + "id": "1bd52930-d783-460a-923b-41a3c37d2f2b", |
| 90 | + "metadata": {}, |
| 91 | + "source": [ |
| 92 | + "## Operating the Buzzer\n", |
| 93 | + "\n", |
| 94 | + "Now that your circuit is built, it's time to use the buzzer. This is done using MicroPython, which is running on the RedBoard.\n", |
| 95 | + "\n", |
| 96 | + "The first step is to connect your RedBoard to a USB port on this computer.\n", |
| 97 | + "\n", |
| 98 | + "Select the \"Connect\" button at the bottom right of this screen and a panel is displayed\n", |
| 99 | + "\n", |
| 100 | + "Select the \"Connect Device\" Button, and when the selection dialog appears, select the port with that displays ***Board in FS mode (...)*** or *TBD*\n", |
| 101 | + "\n", |
| 102 | + "\n", |
| 103 | + "\n", |
| 104 | + "With the RedBoard connected, use the following MicroPython commands to move the servo. \n", |
| 105 | + "\n", |
| 106 | + "### Using MicroPython\n", |
| 107 | + "\n", |
| 108 | + "The following MicroPython commands are entered to operate the buzzer. \n", |
| 109 | + "\n", |
| 110 | + "**REMEMBER** To enter a MicroPython command, hold down either the Control (on Windows) or Command (on Mac) key when pressing *Enter*\n", |
| 111 | + "\n", |
| 112 | + "#### Step 1 - Setup\n", |
| 113 | + "\n", |
| 114 | + "Lets start by importing any of the libaries we plan on using and setting up our pins." |
| 115 | + ] |
| 116 | + }, |
| 117 | + { |
| 118 | + "cell_type": "code", |
| 119 | + "execution_count": null, |
| 120 | + "id": "aafcc22d", |
| 121 | + "metadata": {}, |
| 122 | + "outputs": [], |
| 123 | + "source": [ |
| 124 | + "from machine import Pin # Allows us to use \"Pin\" to use code to interface with the pins on our board\n", |
| 125 | + "from machine import PWM # Allows us to use \"PWM\" (pulse-width modulation) to control the brightness of our LED\n", |
| 126 | + "\n", |
| 127 | + "pwmSpeaker = PWM(Pin(34), freq=0, duty_u16=0) # Create a PWM object on pin 34 with a frequency of 0Hz and an initial \"on time\" of 0 (off)" |
| 128 | + ] |
| 129 | + }, |
| 130 | + { |
| 131 | + "cell_type": "markdown", |
| 132 | + "id": "b1545bf1", |
| 133 | + "metadata": {}, |
| 134 | + "source": [ |
| 135 | + "#### Step 2 - Creating a Function to Play Notes\n", |
| 136 | + "Next, let's create a function to play notes. Let's convert the table below into `list`s. Let's also allow the function to take in a character representing a note to play and a number of beats to play it. Then we can look up that note in our `list`s and play the corresponding frequency. \n", |
| 137 | + "\n", |
| 138 | + "Advanced Tip: Python actually has a \"fancier\" data structure called a [dictionary](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) that makes this kind of lookup much easier.\n", |
| 139 | + "\n", |
| 140 | + "| Note | Frequency (Hz) |\n", |
| 141 | + "|------|---------------|\n", |
| 142 | + "| c | 131 |\n", |
| 143 | + "| d | 147 |\n", |
| 144 | + "| e | 165 |\n", |
| 145 | + "| f | 175 |\n", |
| 146 | + "| g | 196 |\n", |
| 147 | + "| a | 220 |\n", |
| 148 | + "| b | 247 |\n", |
| 149 | + "| C | 262 |\n", |
| 150 | + "| D | 294 |\n", |
| 151 | + "| E | 330 |\n", |
| 152 | + "| F | 349 |\n", |
| 153 | + "| G | 392 |\n", |
| 154 | + "| A | 440 |\n", |
| 155 | + "| B | 494 |" |
| 156 | + ] |
| 157 | + }, |
| 158 | + { |
| 159 | + "cell_type": "code", |
| 160 | + "execution_count": null, |
| 161 | + "id": "b9f2133d", |
| 162 | + "metadata": {}, |
| 163 | + "outputs": [], |
| 164 | + "source": [ |
| 165 | + "from time import sleep # Import the sleep function to pause execution for a specified duration\n", |
| 166 | + "beatLength = 0.25 # Define the length of a beat in seconds (0.5 seconds). Change this to adjust the tempo of the music.\n", |
| 167 | + "restLength = 0.05 # Define the length of a rest in seconds (0.25 seconds). Change this to adjust the length of pauses in the music.\n", |
| 168 | + "\n", |
| 169 | + "def play(note, beats):\n", |
| 170 | + " # To define a list we put it in square brackets []\n", |
| 171 | + " # These list is used to look up the frequency of each note\n", |
| 172 | + " notes = ['c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'D', 'E', 'F', 'G', 'A', 'B', ' ']\n", |
| 173 | + " # This list contains the frequencies corresponding to the notes in the \"notes\" list\n", |
| 174 | + " # For example the 4th item in the \"notes\" list is 'f' and the 4th item in the \"frequencies\" list is 175Hz, its frequency\n", |
| 175 | + " frequencies = [131, 147, 165, 175, 196, 220, 247, 262, 294, 330, 349, 392, 440, 494, 0]\n", |
| 176 | + " \n", |
| 177 | + " # We will now search our lists for a match\n", |
| 178 | + " frequency = 0 \n", |
| 179 | + "\n", |
| 180 | + " # This loop will step through each note in the \"notes\" list and look for a match with the \"note\" variable\n", |
| 181 | + " # Notice the len(notes) function returns the number of items in the \"notes\" list\n", |
| 182 | + " # The range function creates a sequence of numbers from 0 to len(notes) - 1\n", |
| 183 | + " # The \"for\" loop will repeat for each number in that sequence\n", |
| 184 | + " for i in range(len(notes)):\n", |
| 185 | + " if notes[i] == note: # If the note matches the current note in the list\n", |
| 186 | + " frequency = frequencies[i] # Get the corresponding frequency\n", |
| 187 | + " \n", |
| 188 | + " pwmSpeaker.freq(frequency) # Set the frequency of the PWM signal to the specified frequency\n", |
| 189 | + " if frequency == 0: # If the frequency is 0, it means we are playing a rest (no sound)\n", |
| 190 | + " pwmSpeaker.duty_u16(0) # Set the duty cycle to 0 (off)\n", |
| 191 | + " else: # If the frequency is not 0, we are playing a note\n", |
| 192 | + " pwmSpeaker.duty_u16(32768) # Set the duty cycle to 50% on time (half as loud as possible)\n", |
| 193 | + " sleep(beats * beatLength) # Wait for the specified number of beats (0.5 seconds per beat)\n", |
| 194 | + " pwmSpeaker.duty_u16(0) # Turn off the speaker by setting duty cycle to 0\n", |
| 195 | + " sleep(beats * restLength) # Wait for the specified number of rests (0.25 seconds per rest)" |
| 196 | + ] |
| 197 | + }, |
| 198 | + { |
| 199 | + "cell_type": "code", |
| 200 | + "execution_count": null, |
| 201 | + "id": "522377ab", |
| 202 | + "metadata": {}, |
| 203 | + "outputs": [], |
| 204 | + "source": [ |
| 205 | + "# Happy Birthday melody using the play() function\n", |
| 206 | + "play('g', 2) # ha\n", |
| 207 | + "play('g', 1) # ppy\n", |
| 208 | + "play('a', 4) # birth\n", |
| 209 | + "play('g', 4) # day\n", |
| 210 | + "play('C', 4) # to\n", |
| 211 | + "play('b', 4) # you\n", |
| 212 | + "\n", |
| 213 | + "play(' ', 2) # pause for 2 beats\n", |
| 214 | + "\n", |
| 215 | + "play('g', 2) # ha\n", |
| 216 | + "play('g', 1) # ppy\n", |
| 217 | + "play('a', 4) # birth\n", |
| 218 | + "play('g', 4) # day\n", |
| 219 | + "play('D', 4) # to\n", |
| 220 | + "play('C', 4) # you\n", |
| 221 | + "\n", |
| 222 | + "play(' ', 2) # pause for 2 beats\n", |
| 223 | + "\n", |
| 224 | + "play('g', 2) # ha\n", |
| 225 | + "play('g', 1) # ppy\n", |
| 226 | + "play('G', 4) # birth\n", |
| 227 | + "play('E', 4) # day\n", |
| 228 | + "play('C', 4) # dear\n", |
| 229 | + "play('b', 4) # your\n", |
| 230 | + "play('a', 6) # name\n", |
| 231 | + "\n", |
| 232 | + "play(' ', 2) # pause for 2 beats\n", |
| 233 | + "\n", |
| 234 | + "play('F', 2) # ha\n", |
| 235 | + "play('F', 1) # ppy\n", |
| 236 | + "play('E', 4) # birth\n", |
| 237 | + "play('C', 4) # day\n", |
| 238 | + "play('D', 4) # to\n", |
| 239 | + "play('C', 6) # you\n" |
| 240 | + ] |
| 241 | + }, |
| 242 | + { |
| 243 | + "cell_type": "markdown", |
| 244 | + "id": "10d5c3fe-852f-42f7-8378-85dc8c8c7c3e", |
| 245 | + "metadata": {}, |
| 246 | + "source": [ |
| 247 | + "## What You Should See\n", |
| 248 | + "When the program begins, a song will play from the buzzer once. Use the potentiometer to adjust the volume.\n", |
| 249 | + "\n", |
| 250 | + "## You've Completed Circuit 2A!\n", |
| 251 | + "\n", |
| 252 | + "Continue to circuit 2B to learn about buttons.\n", |
| 253 | + "\n", |
| 254 | + "" |
| 255 | + ] |
| 256 | + } |
| 257 | + ], |
| 258 | + "metadata": { |
| 259 | + "kernelspec": { |
| 260 | + "display_name": "MicroPython upydevice kernel", |
| 261 | + "language": "python", |
| 262 | + "name": "micropython-upydevice" |
| 263 | + }, |
| 264 | + "language_info": { |
| 265 | + "codemirror_mode": "python", |
| 266 | + "file_extension": ".py", |
| 267 | + "mimetype": "text/x-python", |
| 268 | + "name": "python", |
| 269 | + "pygments_lexer": "python" |
| 270 | + } |
| 271 | + }, |
| 272 | + "nbformat": 4, |
| 273 | + "nbformat_minor": 5 |
| 274 | +} |
0 commit comments