E91a Fall 2010
Final Lab Mini-project
The objective of this project was to enable a user to program a sequence of tones and play them back. The user interface consists of three rotary encoders, three push-button switches, and a numeric LCD screen. Arrays of 64 buttons and 64 LEDs were added to enable quicker selection of notes. The tune is played back by varying the frequency of a synthesized sine wave.
Earlier in the course, we programmed the microcontroller to synthesize sinusoidal tones. This proved to be an inspiration to put a series of tones in sequence; to make the MSP430 play simple tunes.
The project uses several interesting technologies. The rotary encoders are a means for a user to intuitively increment and decrement values. Unlike potentiometers, which are have a continuous range between 0% and 100%, encoders produce discreet steps, read as pulses, in one direction or another. The ones used in this project have 12 detents, which provide tactile feedback to the user. Encoder and push-button events are handled in a simple interrupt service routine.
A touch sensitive button has one terminal pulled high and the other pulled low by a weak resistor. When a finger is places across the contacts, the conductance of the skin pulls the low terminal high. The “buttonArray” is an 8-by-8 grid of such contact pairs. One column is pulled high at a time, while the rows are read with I/O pins.
An array of white LED’s was included as well. This is used in a similar fashion: one column is pulled high at a time, while the proper row pins are set low. Since the LED’s operate at 5 volts, intermediate logic was added to step up from the 3.3v microcontroller level.
The sine wave signal synthesis used an algorithm similar to that used in class.
The LCD was used to display information about the current note.
P1: Encoder ‘A’ signals (3), pushbuttons (3), and Encoder board power (2).
P2: LED array columns (3 bits), LED array common (1), unused (4)
P3: touchArray rows (8)
P4: Encoder ‘B’ signals (3), LED (1), touchArray power (2), unused (2)
P5: LCD common (4), unused (4)
P6: touchArray columns (8)
P7: LED array rows (8)
P8: LCD (8)
P9: LCD (8)
P10:LCD (6), unused (2)
See schematic for details.
On the user-interface level, the program has two primary modes: play, and edit. Edit mode is indicated by the LED on the encoder board and the envelope symbol on the LCD.
note name mode
note name mode
There are three note-name modes: sharp, flat, and number. In our musical system, notes with accidentals can be represented as sharp or flat, for example, the note slightly higher than A is A♯ (a-sharp), and the note slightly lower than B is B♭. A♯ and B♭ are the same note, but we call them differently things in different cases. Usually, a tune will use only flats or only sharps, depending on factors like key.
The “tune navigation” knob manually advances to the next note.
The “tempo” knob set changes the tempo. Tempo can range from 30bpm to 500bpm.
The program performs a number of operations:
Operations that can be triggered directly by input signals are performed in an I/O interrupt service routine.
Operations that demand precise timing are triggered by timers.
Operations that should happen as frequently as possible, but not necessarily at precise or even times are called by a loop in main().
Encoders and buttons
The quadrature encoders produce two signals; out-of-phase square waves, called A and B.
The falling edge of A indicates the encoder has turned about 30˚ (360˚/12), or one detent. The level of B at that moment indicates direction: high means clockwise, low means counterclockwise. The detents provide tactile feedback, giving the user a sense of how much the knob has turned.
The encoder ‘A’ signals and (active low) buttons were connected to PORT1 and configured to fire interrupts on falling edges. The ISR (interrupt service routine) handle the events as appropriate.
Sine wave synthesis
The sine wave algorithm, executed each step, was:
Initial conditions were x=250,dx=0.
This is a simple Euler method to solving the equation . To better understand the first line, imagine a mass hanging on a spring. Initially, the spring is pulled 250 units away from it’s resting point and releassed. Every unit of time, the mass accelerates an amount negatively proportional to it’s position. The variable stepShift controls; higher numbers right-shift dx and make steps smaller. Therefore .
In this program, frequencies are represented by integers, and stored in an array called piano, indexed by piano key number from 1 to 88 (0 means off, a rest). Rounding to integer decreased accuracy by as much as 3% for the lowest frequencies, but much smaller amounts for higher ranges.
Frequency is set in two ways: by changing the timeout of the timer (TACCR0=FCONST/frequency) and the stepsize (stepShift). Changing the timer yields precise changes in frequency, while changing stepShift gives rougher control. If FCONST is too small, the synthesis ISR runs nearly all of the time, leaving no time for other things to happen, and effectively freezing the processor. Accuracy also decreases for smaller values of FCONST. On the other hand, larger step-sizes create a rougher, nosier signal. A compromise was made between the two factors:
frequency range (Hz)
Values for FCONST were found by trial and error.
Notes higher than 80 (2.6kHz) were too fast for this configuration. A modified algorithm (simple square wave) or an increased master clock may have allowed this, but those frequencies are hardly important. To ensure the continued operation of the synthesizer, x and dx are reset to initial conditions when frequency is changed.
The sequence of tones was stored in an array of piano key numbers as chars. By default, the array contains a 96-note fiddle tune similar to Swallowtail Jig. This, of course, may be modified by the user.
When playing, the array was stepped through in intervals determined by Timer B. Tempo was represented by beats-per-minute (bpm) and set by: TBCCR0=1966050/bpm.
The array used was a white 8-by-8 cathode-row LED “dot matrix”. This consists of 64 LED’s arranged in a grid, like so:
The LED’s are flashed one column at a time by raising one column wire at a time and pulling the appropriate row wires low. This process is fast enough to appear continuous. The array is scanned in this way in the run loop, meaning whenever the processor isn’t busy doing anything else. Since the LED’s require 5 volts and the microcontroller runs on 3.3v, intermediate logic was used. Row wires were passed through an octal buffer, while the column signal was fed as a three-bit address to a decoder.
Resistive “touch buttons” work by testing the resistance across a pair of electrodes. One electrode is tied low with a weak resistor (10M) and the other is pulled high. A typical finger touch has a resistance between 200k and 2M. When a finger touches both electrodes, the output is pulled high.
The button-array consists of a grid of bare steel wire woven into a perforated breadboard. The wires exposed on the front of the board form a matrix of terminal pairs. Each row wire is tied to ground with a weak resistor. The array is read by pulling column wires high one at a time and reading row wires. Like the LED flashing, this operation doesn’t require precise or regular timing, and is places in the main run loop. Since the buttons don’t need to be polled as frequently as the LED are flashed, polling occurs one every 100 flashes. Limitations to this polling method will be discussed in later sections.
The MSP430x4xx’s built-in LCD controller driver makes the LCD relatively easy to use. A portion of memory is mapped to the elements of the display. Sample code was provided in class to display numbers. This was modified to display two number, or a number and a note name, as well as various symbols. LCD code was placed in a separate file from the other code and a header file was used to interface with the external functions. The LCD is updated whenever the user provides input, or when the next note a tune begins.
The LCD telling us the 32nd note is D♯3, and that we are playing, in edit mode.
Overall, the system works as expected. Many improvements and additions are possible.
Although all implemented functionality worked to some extent, every part of the system could be improved, and many features were left unimplemented.
Many of the issues encountered involved finding ports or pins that functioned properly. On the “MSP430FG4618/F2013 Experimenter’s Board,” many of the pins are connected to hardware on the board. Although this usually doesn’t effect pin functionality, it can, and sometimes does. For example, P2.1 and P2.2 are connected to LED’s. Port2 was initially connected to the rows of the touchArray, but the LED’s caused trouble.
Another strange issue occurred when initially testing the encoders. Both A and B signals went to P1. The interrupt would fire when A went low, but the value of B was often incorrect. Once the B signals were moved to another port, they could be read properly.
The LED’s were initially connected directly to the microcontroller and were provided insufficient voltage (3.3v). The added TTL logic resolved this issue.
The most significant problem that currently exists is the conflict on P6.5. Port 6 is used to scan the touchArray. P6.5 connects the DAC to the audio output jack. This presented a problem when the touchArray was first added to the system. The conflict somewhat resolved by not using P6.5 for buttons. The 6th column of buttons behaves sporadically as a result. One possible solution would be to use would be to utilize some other unused pins for the touchArray.
There is an audible gap or discontinuity between tones. This may be due to the amount of processing that occurs in ISR’s, including LCD updates. A solution might involve removing most of the processing from the ISR and placing it in the main run loop. This would introduce some added complexity. Swapping TIMERA and TIMERB would give synthesis a higher priority interrupt. Making the sinewave continuous at frequency changes might be accomplished by only applying changes at certain points in the cycle.
Tone frequencies are rounded to integer and not tuned precisely. It may be possible to derive tuning constants mathematically to achieve the highest precision.
The LED and touchArray are not used to their full potential. Possible uses include showing the upcoming tone sequence. Buttons could be mapped to notes in a more useful way.
Currently, the tune is a fixed size. Ideally, the user could make a tune of any size.
Currently, the tune is stored in volatile memory. Ideally, the tune could be stored to flash.
Notes could have more attributes, such as duration and volume.
Another possible expansion would be to allow the creation, and possibly, the sequencing of multiple ‘tunes.’
"LC2088TW1C: 2.3” (58mm) 8x8 White LED Dot Matrix (Cathode Row)”
“Piano key frequencies”
“74LS244” Octal Buffer
“MSP430x4xx Family User’s Guide”
various others, including class resources and sample code, and TI sample code.