Level: Beginner
Skills Required: Propeller C programming, breadboard circuit-building
Hours to Complete: 1
This project will show you how to build a 4-note musical ‘keyboard’ where you use tilt, rather than actual buttons or keys, to control the notes you play. We also added LEDs that light up in different colors depending on which note is playing, because no fun project is complete without LED lights! This activity is suitable to be built on a Propeller Activity Board but it is also available for the BASIC Stamp HomeWork Board, accessible on its own project page.
If you know how to program in Propeller C but are unfamiliar with PBASIC, this could be a great time to introduce yourself to one of our most popular programming languages! The BASIC Stamp version of the Tilt Tones project uses simple concepts taught in the What’s a Microcontroller text, which is available in print or as a pdf.
If you are new to the Propeller microcontroller, circuit-building on a breadboard, or programming, it would be a good idea to review the following before beginning:
Figure 1 – Tilt Tones Schematics (Propeller Activity Board)
Figure 1 shows the schematics for connecting the 4-Directional Tilt Sensor, Piezo Speaker and 4 LED lights.
Figure 2 – Tilt Tones Wiring Diagram (Propeller Activity Board)
When you have finished setting up your board, it should look something like the wiring diagram in Figure 2. If your LED leads are too long, they can be cut, but be sure to make note of which side is the cathode, and which is the anode. If you look at the top of the LED, the cathode is the side where the edge is either flattened or has a small notch in it.
Time to play your Tilt Tones musical instrument!
/* Propeller Tilt-Tones.c */ #include "simpletools.h" // Include simpletools library int led[4] = {4, 6, 8, 10}; // Array of I/O pins for LEDs int note[4] = {1175, 1319, 1480, 1760}; // Array of note frequencies in Hz for piezo int sensor[2] = {14, 15}; // Array for I/O pin input states from sensor int beat = 500; // How long to play each note, in ms int index = 0; // For sensor input states to select array elements int main() // main function { set_directions(sensor[1], sensor[0], 0b00); // Set I/O pins for sensor to input set_directions(led[3], led[0], 0b1010101); // Set I/O pins for LEDs to output // (skipping odd-number pins) while(1) // Repeat indefinitely { index = get_states(sensor[1],sensor[0]); // Check sensor I/O pins and put states into index var high(led[index]); // Turn on LED, using index element in led array freqout(1, beat, note[index]); // Play index element freq. in note array on P1 piezo low(led[index]); // Turn LED off } }
If nothing lights up when you try the circuit, double check that you have the LEDs’ cathode leads connected properly to GND and not to the I/O pins.
The 4-Directional Tilt Sensor uses two I/O pins; we have them connected to P14 and P15 in our example. The diagram below shows what each I/O pin will detect when the sensor is tilted in each direction.
Now, let’s take a peek inside the program. First, it includes the simpletools library so we can use its handy functions:
#include "simpletools.h"
Next come three arrays, named led, note, and sensor.
int led[4] = {4, 6, 8, 10}; int note[4] = {1175, 1319, 1480, 1760}; int sensor[2] = {14, 15};
The 4-element led array holds I/O pin numbers for the LED circuits built on the breadboard. Similarly, the 4-element note array holds four different frequencies, which will be used to play notes on the piezospeaker. Finally, the 2-element sensor array holds the I/O pin numbers for the connections to the tilt sensor.
Next, two more variables, beat and index, are declared and initialized.
int beat = 500; int index = 0;
Inside the main routine, the first task is to set the direction for the I/O pins connected to the sensor. This is done with the set_directions function; notice that the function call uses the sensor array’s element numbers rather than the I/O pin numbers directly. The binary bit pattern 0b00 sets both pins to input.
int main() { set_directions(sensor[1], sensor[0], 0b00);
Now for the action. The code inside the while(1) loop checks the sensor output, and uses that information to select a note to play and an LED to light up.
index = get_states(sensor[1],sensor[0]);
The call to the get_states function translates to “check the state of the two I/O pins named in the sensor array (P15, P14) to see if the sensor is sending 0 or 1, and store those two values as the last two bits of the index variable.” The possible combinations are 00, 01, 10, 11, which are 0, 1, 2, 3 in decimal.
Now, the freshly-set index variable is used to select the “index-th” elements from the led and freqout arrays. For example, if you tilt the board towards you, P14 and P15 both detect 0, making the last two bits of index 00. The 0th element in the led array is 4 (counting from zero) and the 0th element of the note array is 1175.
high(led[index]); freqout(1, beat, note[index]); low(led[index]); } }
So, to continue with this example, high(led[index]) becomes high(4), to turn on the P4 LED. Likewise, the call to freqout plays a 1175 Hz frequency from the note array on the P1 piezo speaker. The note lasts for 500 ms, since that’s how beat was initialized. Finally, the low function call turns the P4 led off again, before the loop repeats.
The example program is easy to modify to make your own custom mini-tunes.
In the example program, recall that the beat variable was initialized to 500. Later, beat is used in the freqout function’s msTime parameter:
freqout(1, beat, note[index])
This makes the note last for 500 ms, giving you a little time to tilt the board to a new position to select a new note before the code repeats the while(1) loop. If you want to slow down the beat, perhaps to practice the movements to play a tune, initialize beat to 750 or 1000. For peppier tunes — and a coordination challenge — try reducing beat to 250.
It’s easy to modify the program to play different notes to make your own 4-note tunes. Simply replace the four elements in the note array with new frequencies.
To make it easier to see which tilt motion will correspond to which frequency (and which LED will light up) you can insert this debugging code into your program, just below the get_states function call:
print("%c", CLS); print("index (binary) = %b\n", index); print("index (decimal) = %d\n", index); print("led = %d\n", led[index]); print("note = %d\n", note[index]);
Here’s what the SimpleIDE Terminal would show if you tilt your Activity Board downward to the right.
The familiar song Mary Had a Little Lamb uses only four notes: A, B, D, and G. It also has a simple, steady beat which works well for our Tilt Tunes toy.
B A G A B B B A A A B D D ma-ry had a lit-tle lamb, lit-tle lamb, lit-tle lamb, B A G A B B B B A A B A G ma-ry had a lit-tle lamb, its fleece was white as snow