Lecture slides and class recording are available below.
You're an engineer and we want you to build a new product for us: the iPoduino!
The specs we want are simple; it needs to play (at least) 3 songs, have a way for the user to select the pitch at which a song is played, select which song will play next, and visually show the user which song is playing.
Pitch: Play music through the speaker using a digital square wave
Design a digital logic circuit that allows a user to select a high or low pitch of song to play.
Put an LED in series with the piezoelectric speaker (buzzer) to act as a music visualizer (it'll blink when the speaker's playing).
Interface: Select next song to be played using the potentiometer knob
You need to find a way to detect which region the potentiometer is turned to (hint: if / else if)
Display: LED indicator that shows which song is being played.
Note: the music visualizer attached to the speaker does not count as a display!
How the display works is up to you—some ideas:
Make LED brightness change for different songs (hint: analogWrite)?
Blink a certain pattern ?
Light up different LEDs corresponding to different songs?
The circuit for this project has four main sections, all of which are connected to your Arduino. Let's talk about what each of them does.
This is a simple series circuit coming from a digital pin on your Arduino, through a resistor, the piezo buzzer, an LED (the music visualizer), and then to GND.
Make sure the + side of the speaker is oriented correctly; it'll be facing the Arduino's digital pin. If the marking has rubbed off the top of your buzzer, you can find another + marking on the back side PCB.
Make sure the LED is oriented correctly too!
If your speaker is really quiet, you can remove the resistor from the speaker circuit and connect the speaker directly to your digital pin. This won't hurt the speaker, but it will be driving your LED with a little more current than it likes. This is technically bad practice but won't hurt the LED enough for us to worry about it, since the speaker has some internal resistance.
You could also build an alternative circuit with two branches coming out of the digital pin: One branch going from the pin to the speaker, and then to GND, and the other branch going from the pin to the resistor, then to the LED, and then to GND. (We draw this circuit on the board at around 1:13:00 in this lecture video). This gives your speaker the full current from the digital pin while still safely limiting the current through the LED.
This potentiometer circuit should look familiar; it's the same one we used last week!
Connect one of the outer pins to 5V, the other to GND, and connect the wiper to an analog input pin.
You'll need to read the potentiometer's position with analogRead() just like in project 1, but this time use if-else statements to check if the potentiometer reading is within certain ranges, then execute different code accordingly.
We'll use digital logic gates to design our pitch selector.
You have AND, OR, and NOT gates in your kit. You can use any combination of these to create a circuit that implements the truth table below:
The logic output is 0 when only the low pitch is selected and is 1 when only the high pitch is selected
00 and 11 are "don't care" states. Because the input combination of neither (00) or both (11) high and low pitch selection isn't possible, the outputs for those inputs don't matter!
You'll use the 5V and ground rails on your breadboard as inputs to your circuit.
Use jumper wires as your high and low pitch selectors (it may be helpful to label your jumpers as "high-pitch" and "low-pitch").
If the user wants to play the high-pitched version of a song, they'll plug the high-pitch jumper into the 5V rail and the low-pitch jumper into the ground rail (or vice versa for a low-pitch selection!)
These are the pinouts for the gates in your kit. You'll be referencing these when placing the gates in your circuit.
This part's up to you! The only requirement is that it's easy to tell which of your songs is playing from the LEDs you use.
Don't forget to connect a current limiting resistor in series with each LED (the 470Ω work well for this, do you remember their color codes?)
Some ideas for your display:
Vary the LED(s) brightness using analogWrite()?
Blink the LED(s) in a different pattern / at a different speed?
Light up multiple LEDs to correspond to different songs?
Here's an example of a truth table and its corresponding circuit.
General steps to follow to connect these on a breadboard are below:
Place the gates you'll be using across the center divide of your breadboard
For each gate, use its pinout diagram to connect inputs to their corresponding pins
Connect the gates to power and ground (shown as VCC and GND on the pinout)
Connect the output pin of a gate to the input pin of the next gate as needed
Connect the final output pin to a digital pin on your Arduino
Here's what this circuit would look like on a breadboard.
Input 1 is connected to the 5V rail, and Input 2 is connected to the ground rail. This means the input selection is currently 10 and has an output of 1.
To change the inputs, simply change which rail your inputs are connected to.
Input 1 is connected to the NOT gate at pin 1A, and the inverted Input 1 exits the NOT gate at pin 1Y (look at the pinout for reference).
The inverted Input 1 is then connected to the OR gate at pin 1B.
Input 2 is connected to the OR gate at pin 1A.
The output of the OR (at pin 1Y) is then fed to the Arduino's D5 pin (where it can be read using a digitalRead() of that pin!).
Remember that this is just an example! You're still responsible for designing your own pitch selector logic circuit.
analogWrite() only works on PWM pins! Look for digital pins with the ~ next to them on your pinout diagram. If you try to use analogWrite() on a non-PWM digital pin, or an analog input pin, the MCU won't output a PWM signal.
You'll need to use PWM pins for the speaker output and any LEDs that you want to control the brightness of.
An important note from the Arduino Reference:
Use of the tone() function interferes with PWM output on pins 3 and 11.
This means you can't use analogWrite() on pins 3 or 11 (but digitalWrite() and digitalRead() will still work on them)
Why does this happen? Our microcontrollers use internal timer circuits to generate the periodic signals used by analogWrite() (PWM waves) and for tone() (square waves). However, the microcontroller on the Arduino Nano has a limited number of timers, and the lower level code used by tone() takes over the timer that outputs signals to pins 3 and 11, blocking analogWrite()'s internal code from generating PWM on those pins.
You can't use anything from an #included file before the #include statement. That's because the contents of the file aren't in-scope until after the line that includes it.
Likewise, the code inside an included file can't access anything that wasn't already in your main sketch file before the include statement.
For example, the following code wouldn't work:
void setup() {
int guests = 2;
int snacksPerPerson = 2;
int snacksNeeded = snackMath(snacksPerPerson, guests);
// snacksNeeded = 2 + 2 * 2 = 6
// 2 snacks per guest plus 2 for me
Serial.print("You need ");
Serial.print(snacksNeeded);
Serial.print(" snacks.");
}
#include "myMathFunction.h"
The compiler would give us the following error at line 4:
error: 'snackMath' was not declared in this scope
In this situation, the compiler isn't able to execute the snackMath() function because it doesn't yet know that function exists (remember, the compiler evaluates our code line by line from top to bottom). The include statement telling the compiler where the function definition is (in myMathFunction.h) hasn't yet been evaluated when snackMath() is called because the #include was placed after the line with the function call.
Download songs.h and place it in the same folder that your sketch .ino is saved in. Any time you #include a file in double quotes (as shown above) the compiler will look for that file in the same location as your sketch file. If you're not sure where the Arduino IDE is saving your sketches, go to File -> Preferences and take note of the Sketchbook location (usually it'll be in your Documents folder on Windows and similar on Mac).
songs.h
This file contains #define statements for the frequency that corresponds to various notes, as well as the definitions of the song functions you'll need to call in your main sketch.
After you load the file into your program (using #include "songs.h") you'll be able to call functions like Empire_low().
Here is an example using a song function:
if ((analogRead(pot) > 512) && (digitalRead(logicOut) == LOW)) {
Elise_low();
}
You can write your own song functions using the notes defined at the top of songs.h!
Here are some songs with labelled notes that you can use for reference when making your own.
Remember, each song you write yourself needs to have a high- and low-pitched version. Check out the song definitions in songs.h for an example!
Here's some pseudocode of what you should expect to have in your program. We recommend using this file as your starting point for the project (it's the same pseudocode we covered in lecture).
Nevertheless, you're always welcome to write the program however you please, as long as it meets the minimum requirements we've talked about above (so in other words, you don't have to use this pseudocode if you don't want to).