teaching machines

Music Mouse, Part II

This post is part of a series of notes and exercises for a summer camp on making musical instruments with Arduino and Pure Data.

We’ll complete the Music Mouse in stages. In this stage, let’s get the joystick behaving like a mouse. We’ll start at a position and allow the joystick to move us around the musical terrain.

Globals

Create two global int variables to hold our x- and y-positions in this 2D musical grid. Initialize them to the MIDI numbers of your favorite notes. To avoid later suffering, give them meaningful names, like x and y.

Centering

In loop, read and print just pin A0 for the moment. This pin will be indirectly applied to move the musician along the x-axis. (It isn’t used to set x directly, as you’ll in a moment.) Upload and run the program. Inspect the values you see and answer these questions:

• What value do you see when the joystick is pushed all the way left?
Something near 0. Hardware imperfections might keep it from reaching 0 exactly.
• What value do you see when the joystick is pushed all the way right?
~1023
• What value do you see when the joystick is idle, not pushed at all?
Around 511.

It’d be nice if pushing left made the number go negative, idle was 0, and pushing right made the number go positive. Let’s make that happen. We want to turn a number in the top range into a number in the bottom range:

$$\begin{array}{lrcrl}[& 0, && 1023 &] \\ && \downarrow && \\ [&-512, && 511 &]\end{array}$$

How do we do that with just math?
Subtract 512 (or an appropriate center for your joystick) from the analog reading.

Center the reading and test that it works.

Sign Zones

For our purposes, we really only care if the joystick is pushed left, right, or not at all. But we currently have a spectrum of 1024 different possible joystick positions. Let’s simplify the positions into three “sign zones”: -1, 0, and 1.

Add a new function with this shape:

int sign(int value) {
}


The function returns an int. Inside this function, write if statements to return -1 if value is less than -10, 1 if value is greater than 10, and 0 otherwise. We allow [-10, 10] to count as idling to handle the electronic noise that makes analog signals jump around. If your joystick gives particularly wild readings, you may need to increase the size of this window.

Back in loop, turn the centered reading into its sign zone. Store the result in a variable named dx—short for delta x.

Print dx. Upload your code and test that it behaves as you expect. If it does, get rid of all your print statements. They will start to drown us in information.

Change Only

As with our other instruments, we only want to act on changes to the sensor. Declare a global variable named old_dx and assign it 0.

Add C++ code to loop equivalent to this pseudocode:

if old_dx and dx are different
increase x-position by dx
print x-position
old_dx = dx

Non-zero Only

When the musician is idling, we don’t really change the x-position in anyway, so let’s add a conditional statement to not do anything when in the idle state:

if old_dx and dx are different
if we're not idling
increase x-position by dx
print x-position
old_dx = dx