<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://hades.mech.northwestern.edu//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=EricWest</id>
	<title>Mech - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://hades.mech.northwestern.edu//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=EricWest"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php/Special:Contributions/EricWest"/>
	<updated>2026-04-22T06:26:32Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.9</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17321</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17321"/>
		<updated>2010-03-17T09:10:51Z</updated>

		<summary type="html">&lt;p&gt;EricWest: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | width1    = 150&lt;br /&gt;
   | width2    = 269&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | header    = Music from the Heart Project&lt;br /&gt;
   | image1    = Music from the heart overview.jpg&lt;br /&gt;
   | caption1  = The full &amp;quot;music suit&amp;quot; on James, with heart rate sensor on his finger. &lt;br /&gt;
   | image2    = Drum overview mfth.jpg&lt;br /&gt;
   | caption2  = A closer view of the drum mechanism&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, and 100 + 75 = 175ms of drive time, the fastest heartbeat our drum could play was 96 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &amp;#039;&amp;#039;&amp;#039;IS MY MATH CORRECT?? SEEMS SLOW TO ME, BUT I GUESS WE HAD TO DO WHAT WE HAD TO DO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency (see [[PIC32MX: FFT of Analog Input]] for more information). Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft. Split-clamp to the motor shaft on the left, drum stick on the right|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17320</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17320"/>
		<updated>2010-03-17T09:10:35Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | width1    = 150&lt;br /&gt;
   | width2    = 269&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | header    = Music from the Heart Project&lt;br /&gt;
   | image1    = Music from the heart overview.jpg&lt;br /&gt;
   | caption1  = The full &amp;quot;music suit&amp;quot; on James, with heart rate sensor on his finger. &lt;br /&gt;
   | image2    = Drum overview mfth.jpg&lt;br /&gt;
   | caption2  = A closer view of the drum mechanism&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, and 100 + 75 = 175ms of drive time, the fastest heartbeat our drum could play was 96 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &amp;#039;&amp;#039;&amp;#039;IS MY MATH CORRECT?? SEEMS SLOW TO ME, BUT I GUESS WE HAD TO DO WHAT WE HAD TO DO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency (see [[PIC32MX: FFT of Analog Input]] for more information). Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft. Split-clamp to the motor shaft on the left, drum stick on the right|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17319</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17319"/>
		<updated>2010-03-17T09:10:15Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | width1    = 150&lt;br /&gt;
   | width2    = 269&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | header    = Music from the Heart Project&lt;br /&gt;
   | image1    = Music from the heart overview.jpg&lt;br /&gt;
   | caption1  = The full &amp;quot;music suit&amp;quot; on James, with heart rate sensor on his finger. &lt;br /&gt;
   | image2    = Drum overview mfth.jpg&lt;br /&gt;
   | caption2  = A closer view of the drum mechanism&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, and 100 + 75 = 175ms of drive time, the fastest heartbeat our drum could play was 96 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &amp;#039;&amp;#039;&amp;#039;IS MY MATH CORRECT?? SEEMS SLOW TO ME, BUT I GUESS WE HAD TO DO WHAT WE HAD TO DO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency (see [[PIC32MX: FFT of Analog Input]] for more information). Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft. Split-clamp to the motor shaft on the left, drum stick on the right|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17318</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17318"/>
		<updated>2010-03-17T09:09:38Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | width1    = 150&lt;br /&gt;
   | width2    = 269&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | header    = Music from the Heart Project&lt;br /&gt;
   | image1    = Music from the heart overview.jpg&lt;br /&gt;
   | caption1  = The full &amp;quot;music suit&amp;quot; on James, with heart rate sensor on his finger. &lt;br /&gt;
   | image2    = Drum overview mfth.jpg&lt;br /&gt;
   | caption2  = A closer view of the drum mechanism&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, and 100 + 75 = 175ms of drive time, the fastest heartbeat our drum could play was 96 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &amp;#039;&amp;#039;&amp;#039;IS MY MATH CORRECT?? SEEMS SLOW TO ME, BUT I GUESS WE HAD TO DO WHAT WE HAD TO DO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency (see [[PIC32MX: FFT of Analog Input]] for more information). Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft. Split-clamp to the motor shaft on the left, drum stick on the right|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Drum_overview_mfth.jpg&amp;diff=17317</id>
		<title>File:Drum overview mfth.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Drum_overview_mfth.jpg&amp;diff=17317"/>
		<updated>2010-03-17T09:02:49Z</updated>

		<summary type="html">&lt;p&gt;EricWest: closer view of the drum used in Music from the Heart.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;closer view of the drum used in Music from the Heart.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17316</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17316"/>
		<updated>2010-03-17T08:58:36Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Drum actuator - Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
[[Image:Music from the heart overview.jpg|thumb|150px|The &amp;quot;music suit&amp;quot; on James, with heart rate detector on his finger.|right]]&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, and 100 + 75 = 175ms of drive time, the fastest heartbeat our drum could play was 96 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &amp;#039;&amp;#039;&amp;#039;IS MY MATH CORRECT?? SEEMS SLOW TO ME, BUT I GUESS WE HAD TO DO WHAT WE HAD TO DO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency (see [[PIC32MX: FFT of Analog Input]] for more information). Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft. Split-clamp to the motor shaft on the left, drum stick on the right|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17315</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17315"/>
		<updated>2010-03-17T08:57:10Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
[[Image:Music from the heart overview.jpg|thumb|150px|The &amp;quot;music suit&amp;quot; on James, with heart rate detector on his finger.|right]]&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, and 100 + 75 = 175ms of drive time, the fastest heartbeat our drum could play was 96 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &amp;#039;&amp;#039;&amp;#039;IS MY MATH CORRECT?? SEEMS SLOW TO ME, BUT I GUESS WE HAD TO DO WHAT WE HAD TO DO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency (see [[PIC32MX: FFT of Analog Input]] for more information). Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft.|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=17314</id>
		<title>ME 333 final projects</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=17314"/>
		<updated>2010-03-17T08:52:22Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Music from the Heart -- Music Suit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See the &amp;#039;&amp;#039;&amp;#039;[[ME 333 end of course schedule]]&amp;#039;&amp;#039;&amp;#039;.  &lt;br /&gt;
&lt;br /&gt;
Final projects for ME 333 in years 2000-2007 can be found&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;[http://lims.mech.northwestern.edu/~design/mechatronics/ here]&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2010 ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Sample Project Title]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
You can copy and paste this wiki code to start your wiki page (but don&amp;#039;t erase this code).  Then replace this text with your own.  A few sentences describing what your project does, with a link to a youtube video.  Look at other final project wiki pages for ideas, but see [[ME 333 end of course schedule]] for more information on what should be included on your wiki page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Furuta Pendulum]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Picture 1.png|thumb|150px|Furuta Pendulum|right]]&lt;br /&gt;
&lt;br /&gt;
The Furuta pendulum, so named because it was first developed by Katsuhisa Furuta, is a rotational inverted pendulum.  In other words, the horizontal arm, which rotates in the horizontal plane, drives the movement of the vertical arm, which is free to rotate in the vertical plane.  Out objective was to build a Furuta pendulum that would hold the vertical arm up, as you can see from the [http://www.youtube.com/watch?v=7DtFLKgNUk4 demonstration video].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Music from the Heart -- Music Suit]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Music from the heart overview.jpg|thumb|150px|The &amp;quot;music suit&amp;quot; on James, with heart rate detector on his finger.|right]]&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Conservation of Angular Momentum Locomotion Robot (Fluffbot)]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
Cute fluffy robot that uses conservation of angular momentum to move forward and backward. The robot&amp;#039;s momentum wheel accelerates in the floor-plane. The robot&amp;#039;s net angular momentum must remain zero-- a steering wheel guides the Fluffbot to accelerate in the opposite direction. This moves the robot forward in a curved path. The momentum wheel and steering wheel then change direction of acceleration. This repeated process moves the Fluffbot forward in a sinusoidal path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Differential Drive Mobile Robot]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
The goal of this project was to create a small differential drive mobile robot that would act as a low cost replacement for the popular E-Puck Robot.  The robot uses hybrid stepper motors to allow it to track its position through odometry, has a laser cut acrylic chassis for easy replication and replacement, and a 1500 mAh, 13.2V battery pack for long run time.  The robot also uses the NU32 board for its control logic and a XBee chip for communication.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ferrofluid Art Display]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Place holder text for caption .|right]]&lt;br /&gt;
&lt;br /&gt;
A little blurb about our Ferrofluid Art Display will go here. Just a few sentences talking about blah blah lkasjdfal hfalsdjh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Can Launching Fridge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:27_Fridge.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
The goal of the can launching fridge was to create a fridge that would, when initiated by either a remote control or a wired push button, automatically load, aim, and fire a can to multiple predetermined locations. The fridge uses a combination of stepper motors, a DC motor, and solenoids to create the ultimate mix of convenience, fun, and refreshment. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[High Speed Motor Control]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:2dofArmSetUp.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
The project suggested was to design a system for high speed motor control using the PIC 32. To demonstrate the motor control, a two degree of freedom (2-DOF) parallelogram robot arm was designed to follow paths specified in a MATLAB gui.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Variable Frequency Electrosense]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:TR_JP_PP-sensor.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
Our objective was to build upon existing research being done at Northwestern utilizing Electrosense technology by testing if information can be derived from varying the emitter frequency. We sought to send sinusoidal waves at discrete frequencies between 100 Hz and 10 kHz and to read in the sensed wave using a PIC 32’s ADC. We then sent the gathered information to a PC for plotting and analysis. By mounting the sensor on a one dimensional linear actuator we are able to gather additional data about objects and perform object detection and identification algorithms. While our initial results have revealed exciting trends, farther research is necessary before any significant conclusions can be made. A [http://www.youtube.com/watch?v=PJY097L2m1M video] of the project is available on YouTube.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Remote Controlled Wiitar]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
This project uses an array of solenoids to depress stings on the neck of a guitar.  A motor over the strings of the guitar turns an arm which strums the instrument, playing the chord depressed by the solenoids.  The system is controlled by a Wii Remote.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[6-DOF PPOD]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
The PPOD-mini is a miniaturized version of the Programmable Part-feeding Oscillatory Device ([http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm PPOD]) found in the Laboratory for Intelligent Mechanical Systems (LIMS).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2009 ==&lt;br /&gt;
&lt;br /&gt;
=== [[Mozart&amp;#039;s Right Hand]] ===&lt;br /&gt;
[[Image:mrh_box.JPG|thumb|150px|Mozart&amp;#039;s Right Hand|right]]&lt;br /&gt;
Mozart&amp;#039;s Right Hand is a musical instrument capable of playing two full octaves of the [http://en.wikipedia.org/wiki/Diatonic_scale Diatonic Scale.]  The user wears a glove on his right hand and uses motions of the hand and fingers to create different notes that are played with a speaker.  The pitch of the note is controlled by the orientation of the user&amp;#039;s hand as he rotates it ether from the wrist, the elbow, or the shoulder.  The LCD on the front of the box tells the user the pitch that corresponds to his or her current hand orientation.  When the user touches together his thumb and index finger, the speaker plays the tone.  A [http://www.youtube.com/watch?v=vec-W4QeHQU video] of Mozart&amp;#039;s Right Hand in action is available on YouTube.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Persistence-of-Vision Display]] ===&lt;br /&gt;
[[Image:Persistence of Vison Display|right|thumb|150px]]&lt;br /&gt;
This is a fully customizable display implemented using the concept of Persistence of Vision. User-specified images (and even moving images) were displayed by rotating a column of LEDs at speeds faster than 300rpm. Each individual LED was modeled as a row of pixels. Conversely, the rotational position of the panel of LEDs represented the pixel columns of the display; the time interval and rotational speed determined the width of the pixel columns. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Rock Paper Scissors Machine]] ===&lt;br /&gt;
[[Image:rps whole thing.JPG|thumb|150px|Rock Paper Scissors Machine|right]]&lt;br /&gt;
A machine that will play a fully functioning, intuitive game of [http://en.wikipedia.org/wiki/Rock-paper-scissors Rock/Paper/Scissors] (abbreviated as RPS) with a user. The machine is represented by a human-like hand, capable of seperate and independant wrist, arm, finger and thumb motion. The players&amp;#039; hand goes into a glove equipped with flex sensors, which wirelessly transmits data to the machine based on what the player chose. The machine then reads this data, randomly chooses a throw of its own, and displays what the machine threw, what the human threw, total win/loss/tie info, and winner/loser both on an [http://en.wikipedia.org/wiki/Lcd LCD] screen and in the form of a thumbs up/down/side motion. Video of the machine in action can be found [http://www.youtube.com/watch?v=xbLNBSTTrcE here.]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Three-speaker Chladni Patterns]] ===&lt;br /&gt;
[[Image:chladni_660hz|right|thumb|150px]]&lt;br /&gt;
This project uses three speakers to generate shapes on a circular aluminum plate depending on which frequency the speakers are playing at. Once the speakers hit a resonant frequency of the plate, salt migrates to the nodes (zero amplitude) regions of the plate to form distinct patterns.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Basketball]] ===&lt;br /&gt;
[[Image:Mechatronics2009Bball|right|thumb|150px]]&lt;br /&gt;
This project consists of a throwing arm propelled by a Pittman motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot; A video can be found [http://www.youtube.com/watch?v=Y466dzP-qiY here].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Drummer]] ===&lt;br /&gt;
[[Image:Robot_Drummer.jpg|thumb|400pix|right|Robot Drummer]]&lt;br /&gt;
The Robot Drummer is a device that demonstrates high-speed motor control by being able to drum when given commands.  Through an RS232 cable, Matlab sends commands to a &amp;quot;master&amp;quot; PIC.  The master then sends the commands to two &amp;quot;slave&amp;quot; PICs through I2C communication.  The slaves take the commands and implement PID control of the motors.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Fish Refuge]] ===&lt;br /&gt;
[[Image:Entire Fish Refuge|right|thumb|200px]]&lt;br /&gt;
The automated fish refuge allows for the controlled movement of a fish refuge with the goal of recording specific behavior.  The mechanical design is completely adjustable and allows adjustable degrees of oscillating movement and orientation of the refuge.  The program is primarily in MATLAB for ease of use and the velocity profile can be a sine, square, triangle, or any function that the user inputs. [http://www.youtube.com/watch?v=wGOKujMhN88 Check out the video!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Marionette]] ===&lt;br /&gt;
[[Image: MarionettePicForIntro.JPG|right|thumb]] The Marionette Project focused on using RC Servos to make a puppet that would do a dance with the press of a button.  There were 5 different dances programmed for the marionette, showcasing different styles of movement.  The movement had 2 degrees of freedom thanks to using 5 bar linkages and 2 RC servos for each arm.  Two more RC Servos were used on the back of the marionette to create the appearance of leg movement.  The movements included a Hula dance, Jumping Jacks, and even some moves right out of Saturday Night Fever.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Monkeybot]] ===&lt;br /&gt;
[[Image:monkeybot_pic|thumb|right|200px|Monkeybot]]&lt;br /&gt;
The monkeybot is a swinging robot capable of moving side to side and climbing.  It consists of a two link, double pendulum system with an electro-magnet on each end.  At the pivot is a DC motor, which provides an input torque and allows the swinging system to gain energy and climb.  Check out the video of the monkeybot climbing [http://www.youtube.com/watch?v=TA2VcH_GDJ0 here] and a later brachiation video [http://www.youtube.com/watch?v=0hfwJEVQyeQ&amp;amp;feature=related here].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[PPOD-mini:  6-DOF Shaker]] ===&lt;br /&gt;
[[Image:PPOD_mini.JPG|thumb|200x200 px|right|PPOD-mini 6-DOF Shaker]]&lt;br /&gt;
The PPOD-mini is a miniaturized version of the Programmable Part-feeding Oscillatory Device ([http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm PPOD]) found in the Laboratory for Intelligent Mechanical Systems (LIMS) at Northwestern. The PPOD-mini utilizes six speakers that act like actuators. The speakers are connected to a acrylic plate via flexures of tygon and iron. In its current implementation, the phase of the speakers can be controlled independently, giving the device six degrees of freedom. The movement of objects placed on the acrylic plate can be controlled by changing the phases of the speakers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Xylophone]] ===&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|200x200 px|right|Automated Xylophone]]&lt;br /&gt;
The Automated Xylophone controls several solenoids which hit various pitches on an actual xylophone based on the note selected.  The device has two main modes: using the keypad, a user can choose to either play notes in real time or store songs to be played back later.  A video of the Automated Xylophone playing in real time mode can be found [http://www.youtube.com/watch?v=_ubpAEyq9kg here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vision-based Cannon]] ===&lt;br /&gt;
[[Image:SM_Gun_Camera_PIC_Setup.JPG|thumb|200x200 px|right|Vision-based Cannon]]&lt;br /&gt;
This project uses a webcam and Matlab to analyze an image and direct a modified USB Missile Launcher to fire at targets found in the image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Butterfly Rolling Manipulation]] ===&lt;br /&gt;
[[Image:Persistence of Vison Display|right|thumb|150px]]&lt;br /&gt;
The Butterfly emulates contact juggling by the stabilization of dynamic rolling.  The apparatus rolls a cylinder by rotating the &amp;quot;hand&amp;quot; using a specific trajectory and is able to move the cylinder from one side to the other without losing contact. A video of the Butterfly captured in high speed can be found [http://www.youtube.com/watch?v=hFafcjA_p7E here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axes, and then tracks the emitter with a laser. [[Media:MT_MS_AZ_TrackerVideo.mp4|See Spot Run.]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This remote control robotic snake uses servo motors with a traveling sine wave motion profile to mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
Featured on [http://blog.makezine.com/archive/2009/03/well_documented_robotic_snake.html Makezine.com].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Programmable Stiffness Joint]] === &lt;br /&gt;
&lt;br /&gt;
[[Image:SteelToePic2.jpg|thumb|200px|The &amp;#039;Steel Toe&amp;#039; programmable stiffness joint|right]]&lt;br /&gt;
&lt;br /&gt;
The Programmable Stiffness Joint varies rotational stiffness as desired by the user.  It is the first step in modeling the mechanical impedance of the human ankle joint (both stiffness and damping) for the purpose of determining the respective breakdown of the two properties over the gait cycle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Magnetic based sample purification]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Continuously Variable Transmission]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:CVT_system.JPG|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This prototype is a proof of concept model of a variable ratio transmission to be implemented in the 2008-2009 Formula SAE competition vehicle.  The gear ratio is determined by the distances between the pulley halves which are controllable electronically.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
[[Image:Team-21-main-picture.JPG|right|thumb|200px]]&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=KhgTNCfdwZw Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|Sweet Baseball Game|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Ballbalancechallenge.JPG|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive game involving ball balancing on a touchscreen with touchscreen feedback and joystick action. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Music_from_the_heart_overview.jpg&amp;diff=17313</id>
		<title>File:Music from the heart overview.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Music_from_the_heart_overview.jpg&amp;diff=17313"/>
		<updated>2010-03-17T08:51:03Z</updated>

		<summary type="html">&lt;p&gt;EricWest: James wearing the music suit and connected to the heart monitor to drive the drum.  For the Music from the Heart project.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;James wearing the music suit and connected to the heart monitor to drive the drum.  For the Music from the Heart project.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17312</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17312"/>
		<updated>2010-03-17T08:47:15Z</updated>

		<summary type="html">&lt;p&gt;EricWest: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, and 100 + 75 = 175ms of drive time, the fastest heartbeat our drum could play was 96 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &amp;#039;&amp;#039;&amp;#039;IS MY MATH CORRECT?? SEEMS SLOW TO ME, BUT I GUESS WE HAD TO DO WHAT WE HAD TO DO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency (see [[PIC32MX: FFT of Analog Input]] for more information). Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft.|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17311</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17311"/>
		<updated>2010-03-17T08:46:40Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Drum actuator - Electrical design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, and 100 + 75 = 175ms of drive time, the fastest heartbeat our drum could play was 96 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &amp;#039;&amp;#039;&amp;#039;IS MY MATH CORRECT?? SEEMS SLOW TO ME, BUT I GUESS WE HAD TO DO WHAT WE HAD TO DO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency (see [[PIC32MX: FFT of Analog Input]] for more information). Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft.|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17310</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17310"/>
		<updated>2010-03-17T08:43:59Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Drum actuator - Electrical design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency (see [[PIC32MX: FFT of Analog Input]] for more information). Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft.|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17309</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17309"/>
		<updated>2010-03-17T08:40:53Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Music Tones - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft.|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  {{multiple image&lt;br /&gt;
   | align     = center&lt;br /&gt;
   | width     = 500&lt;br /&gt;
   | image1    = T21_musicckt_png.PNG&lt;br /&gt;
   | caption1  = Music circuit diagram. The summing amplifier is not shown.&lt;br /&gt;
   | image2    = Solder board mfth.jpg&lt;br /&gt;
   | alt2      = Red cartouche&lt;br /&gt;
   | caption2  = Music chips are in the center of the board. H-bridge for motor driving is on the far right, along with the power supply plug. The left side is an unsuccessful attempt at moving the heart rate circuitry to the solder board&lt;br /&gt;
  }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Solder_board_mfth.jpg&amp;diff=17305</id>
		<title>File:Solder board mfth.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Solder_board_mfth.jpg&amp;diff=17305"/>
		<updated>2010-03-17T08:18:00Z</updated>

		<summary type="html">&lt;p&gt;EricWest: Solder board with music-generating chips, motor-driving h-bridges, and unused heart rate monitoring circuitry attached to a PIC32.  Used in the Music from the Heart project.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Solder board with music-generating chips, motor-driving h-bridges, and unused heart rate monitoring circuitry attached to a PIC32.  Used in the Music from the Heart project.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17301</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17301"/>
		<updated>2010-03-17T08:00:41Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Drum actuator - Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Drum stick mount mfth.jpg|thumb|200px|Attachment for the drumstick to the motor shaft.|right]]&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.75&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motor mount mfth.jpg|thumb|200px|Mounting bracket for the motor-stick assembly.|right]]&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum and holes in the face of the motor.  A sheet metal bracket with holes in the appropriate places attached the motor to two of the tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.75&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*2 pop rivets&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Motor_mount_mfth.jpg&amp;diff=17299</id>
		<title>File:Motor mount mfth.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Motor_mount_mfth.jpg&amp;diff=17299"/>
		<updated>2010-03-17T07:57:46Z</updated>

		<summary type="html">&lt;p&gt;EricWest: Bracket mount for the motor-stick assembly.  The existing tuning screws were used to secure the bracket to the drum.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Bracket mount for the motor-stick assembly.  The existing tuning screws were used to secure the bracket to the drum.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Drum_stick_mount_mfth.jpg&amp;diff=17295</id>
		<title>File:Drum stick mount mfth.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Drum_stick_mount_mfth.jpg&amp;diff=17295"/>
		<updated>2010-03-17T07:52:59Z</updated>

		<summary type="html">&lt;p&gt;EricWest: Mount to attach the drum stick to the drive shaft of the motor for the Music from the Heart project.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Mount to attach the drum stick to the drive shaft of the motor for the Music from the Heart project.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=17293</id>
		<title>ME 333 final projects</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=17293"/>
		<updated>2010-03-17T07:45:26Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Music from the Heart -- Music Suit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See the &amp;#039;&amp;#039;&amp;#039;[[ME 333 end of course schedule]]&amp;#039;&amp;#039;&amp;#039;.  &lt;br /&gt;
&lt;br /&gt;
Final projects for ME 333 in years 2000-2007 can be found&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;[http://lims.mech.northwestern.edu/~design/mechatronics/ here]&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2010 ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Sample Project Title]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
You can copy and paste this wiki code to start your wiki page (but don&amp;#039;t erase this code).  Then replace this text with your own.  A few sentences describing what your project does, with a link to a youtube video.  Look at other final project wiki pages for ideas, but see [[ME 333 end of course schedule]] for more information on what should be included on your wiki page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Furuta Pendulum]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Picture 1.png|thumb|150px|Furuta Pendulum|right]]&lt;br /&gt;
&lt;br /&gt;
The Furuta pendulum, so named because it was first developed by Katsuhisa Furuta, is a rotational inverted pendulum.  In other words, the horizontal arm, which rotates in the horizontal plane, drives the movement of the vertical arm, which is free to rotate in the vertical plane.  Out objective was to build a Furuta pendulum that would hold the vertical arm up, as you can see from the [http://www.youtube.com/watch?v=7DtFLKgNUk4 demonstration video].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Music from the Heart -- Music Suit]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Conservation of Angular Momentum Locomotion Robot (Fluffbot)]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
Cute fluffy robot that uses conservation of angular momentum to move forward and backward. The robot&amp;#039;s momentum wheel accelerates in the floor-plane. The robot&amp;#039;s net angular momentum must remain zero-- a steering wheel guides the Fluffbot to accelerate in the opposite direction. This moves the robot forward in a curved path. The momentum wheel and steering wheel then change direction of acceleration. This repeated process moves the Fluffbot forward in a sinusoidal path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Differential Drive Mobile Robot]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
The goal of this project was to create a small differential drive mobile robot that would act as a low cost replacement for the popular E-Puck Robot.  The robot uses hybrid stepper motors to allow it to track its position through odometry, has a laser cut acrylic chassis for easy replication and replacement, and a 1500 mAh, 13.2V battery pack for long run time.  The robot also uses the NU32 board for its control logic and a XBee chip for communication.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ferrofluid Art Display]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Place holder text for caption .|right]]&lt;br /&gt;
&lt;br /&gt;
A little blurb about our Ferrofluid Art Display will go here. Just a few sentences talking about blah blah lkasjdfal hfalsdjh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Can Launching Fridge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:27_Fridge.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
The goal of the can launching fridge was to create a fridge that would, when initiated by either a remote control or a wired push button, automatically load, aim, and fire a can to multiple predetermined locations. The fridge uses a combination of stepper motors, a DC motor, and solenoids to create the ultimate mix of convenience, fun, and refreshment. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[High Speed Motor Control]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:2dofArmSetUp.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
The project suggested was to design a system for high speed motor control using the PIC 32. To demonstrate the motor control, a two degree of freedom (2-DOF) parallelogram robot arm was designed to follow paths specified in a MATLAB gui.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Variable Frequency Electrosense]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:TR_JP_PP-sensor.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
Our objective was to build upon existing research being done at Northwestern utilizing Electrosense technology by testing if information can be derived from varying the emitter frequency. We sought to send sinusoidal waves at discrete frequencies between 100 Hz and 10 kHz and to read in the sensed wave using a PIC 32’s ADC. We then sent the gathered information to a PC for plotting and analysis. By mounting the sensor on a one dimensional linear actuator we are able to gather additional data about objects and perform object detection and identification algorithms. While our initial results have revealed exciting trends, farther research is necessary before any significant conclusions can be made. A [http://www.youtube.com/watch?v=PJY097L2m1M video] of the project is available on YouTube.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Remote Controlled Wiitar]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
This project uses an array of solenoids to depress stings on the neck of a guitar.  A motor over the strings of the guitar turns an arm which strums the instrument, playing the chord depressed by the solenoids.  The system is controlled by a Wii Remote.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[6-DOF PPOD]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
The PPOD-mini is a miniaturized version of the Programmable Part-feeding Oscillatory Device ([http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm PPOD]) found in the Laboratory for Intelligent Mechanical Systems (LIMS).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2009 ==&lt;br /&gt;
&lt;br /&gt;
=== [[Mozart&amp;#039;s Right Hand]] ===&lt;br /&gt;
[[Image:mrh_box.JPG|thumb|150px|Mozart&amp;#039;s Right Hand|right]]&lt;br /&gt;
Mozart&amp;#039;s Right Hand is a musical instrument capable of playing two full octaves of the [http://en.wikipedia.org/wiki/Diatonic_scale Diatonic Scale.]  The user wears a glove on his right hand and uses motions of the hand and fingers to create different notes that are played with a speaker.  The pitch of the note is controlled by the orientation of the user&amp;#039;s hand as he rotates it ether from the wrist, the elbow, or the shoulder.  The LCD on the front of the box tells the user the pitch that corresponds to his or her current hand orientation.  When the user touches together his thumb and index finger, the speaker plays the tone.  A [http://www.youtube.com/watch?v=vec-W4QeHQU video] of Mozart&amp;#039;s Right Hand in action is available on YouTube.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Persistence-of-Vision Display]] ===&lt;br /&gt;
[[Image:Persistence of Vison Display|right|thumb|150px]]&lt;br /&gt;
This is a fully customizable display implemented using the concept of Persistence of Vision. User-specified images (and even moving images) were displayed by rotating a column of LEDs at speeds faster than 300rpm. Each individual LED was modeled as a row of pixels. Conversely, the rotational position of the panel of LEDs represented the pixel columns of the display; the time interval and rotational speed determined the width of the pixel columns. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Rock Paper Scissors Machine]] ===&lt;br /&gt;
[[Image:rps whole thing.JPG|thumb|150px|Rock Paper Scissors Machine|right]]&lt;br /&gt;
A machine that will play a fully functioning, intuitive game of [http://en.wikipedia.org/wiki/Rock-paper-scissors Rock/Paper/Scissors] (abbreviated as RPS) with a user. The machine is represented by a human-like hand, capable of seperate and independant wrist, arm, finger and thumb motion. The players&amp;#039; hand goes into a glove equipped with flex sensors, which wirelessly transmits data to the machine based on what the player chose. The machine then reads this data, randomly chooses a throw of its own, and displays what the machine threw, what the human threw, total win/loss/tie info, and winner/loser both on an [http://en.wikipedia.org/wiki/Lcd LCD] screen and in the form of a thumbs up/down/side motion. Video of the machine in action can be found [http://www.youtube.com/watch?v=xbLNBSTTrcE here.]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Three-speaker Chladni Patterns]] ===&lt;br /&gt;
[[Image:chladni_660hz|right|thumb|150px]]&lt;br /&gt;
This project uses three speakers to generate shapes on a circular aluminum plate depending on which frequency the speakers are playing at. Once the speakers hit a resonant frequency of the plate, salt migrates to the nodes (zero amplitude) regions of the plate to form distinct patterns.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Basketball]] ===&lt;br /&gt;
[[Image:Mechatronics2009Bball|right|thumb|150px]]&lt;br /&gt;
This project consists of a throwing arm propelled by a Pittman motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot; A video can be found [http://www.youtube.com/watch?v=Y466dzP-qiY here].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Drummer]] ===&lt;br /&gt;
[[Image:Robot_Drummer.jpg|thumb|400pix|right|Robot Drummer]]&lt;br /&gt;
The Robot Drummer is a device that demonstrates high-speed motor control by being able to drum when given commands.  Through an RS232 cable, Matlab sends commands to a &amp;quot;master&amp;quot; PIC.  The master then sends the commands to two &amp;quot;slave&amp;quot; PICs through I2C communication.  The slaves take the commands and implement PID control of the motors.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Fish Refuge]] ===&lt;br /&gt;
[[Image:Entire Fish Refuge|right|thumb|200px]]&lt;br /&gt;
The automated fish refuge allows for the controlled movement of a fish refuge with the goal of recording specific behavior.  The mechanical design is completely adjustable and allows adjustable degrees of oscillating movement and orientation of the refuge.  The program is primarily in MATLAB for ease of use and the velocity profile can be a sine, square, triangle, or any function that the user inputs. [http://www.youtube.com/watch?v=wGOKujMhN88 Check out the video!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Marionette]] ===&lt;br /&gt;
[[Image: MarionettePicForIntro.JPG|right|thumb]] The Marionette Project focused on using RC Servos to make a puppet that would do a dance with the press of a button.  There were 5 different dances programmed for the marionette, showcasing different styles of movement.  The movement had 2 degrees of freedom thanks to using 5 bar linkages and 2 RC servos for each arm.  Two more RC Servos were used on the back of the marionette to create the appearance of leg movement.  The movements included a Hula dance, Jumping Jacks, and even some moves right out of Saturday Night Fever.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Monkeybot]] ===&lt;br /&gt;
[[Image:monkeybot_pic|thumb|right|200px|Monkeybot]]&lt;br /&gt;
The monkeybot is a swinging robot capable of moving side to side and climbing.  It consists of a two link, double pendulum system with an electro-magnet on each end.  At the pivot is a DC motor, which provides an input torque and allows the swinging system to gain energy and climb.  Check out the video of the monkeybot climbing [http://www.youtube.com/watch?v=TA2VcH_GDJ0 here] and a later brachiation video [http://www.youtube.com/watch?v=0hfwJEVQyeQ&amp;amp;feature=related here].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[PPOD-mini:  6-DOF Shaker]] ===&lt;br /&gt;
[[Image:PPOD_mini.JPG|thumb|200x200 px|right|PPOD-mini 6-DOF Shaker]]&lt;br /&gt;
The PPOD-mini is a miniaturized version of the Programmable Part-feeding Oscillatory Device ([http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm PPOD]) found in the Laboratory for Intelligent Mechanical Systems (LIMS) at Northwestern. The PPOD-mini utilizes six speakers that act like actuators. The speakers are connected to a acrylic plate via flexures of tygon and iron. In its current implementation, the phase of the speakers can be controlled independently, giving the device six degrees of freedom. The movement of objects placed on the acrylic plate can be controlled by changing the phases of the speakers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Xylophone]] ===&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|200x200 px|right|Automated Xylophone]]&lt;br /&gt;
The Automated Xylophone controls several solenoids which hit various pitches on an actual xylophone based on the note selected.  The device has two main modes: using the keypad, a user can choose to either play notes in real time or store songs to be played back later.  A video of the Automated Xylophone playing in real time mode can be found [http://www.youtube.com/watch?v=_ubpAEyq9kg here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vision-based Cannon]] ===&lt;br /&gt;
[[Image:SM_Gun_Camera_PIC_Setup.JPG|thumb|200x200 px|right|Vision-based Cannon]]&lt;br /&gt;
This project uses a webcam and Matlab to analyze an image and direct a modified USB Missile Launcher to fire at targets found in the image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Butterfly Rolling Manipulation]] ===&lt;br /&gt;
[[Image:Persistence of Vison Display|right|thumb|150px]]&lt;br /&gt;
The Butterfly emulates contact juggling by the stabilization of dynamic rolling.  The apparatus rolls a cylinder by rotating the &amp;quot;hand&amp;quot; using a specific trajectory and is able to move the cylinder from one side to the other without losing contact. A video of the Butterfly captured in high speed can be found [http://www.youtube.com/watch?v=hFafcjA_p7E here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axes, and then tracks the emitter with a laser. [[Media:MT_MS_AZ_TrackerVideo.mp4|See Spot Run.]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This remote control robotic snake uses servo motors with a traveling sine wave motion profile to mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
Featured on [http://blog.makezine.com/archive/2009/03/well_documented_robotic_snake.html Makezine.com].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Programmable Stiffness Joint]] === &lt;br /&gt;
&lt;br /&gt;
[[Image:SteelToePic2.jpg|thumb|200px|The &amp;#039;Steel Toe&amp;#039; programmable stiffness joint|right]]&lt;br /&gt;
&lt;br /&gt;
The Programmable Stiffness Joint varies rotational stiffness as desired by the user.  It is the first step in modeling the mechanical impedance of the human ankle joint (both stiffness and damping) for the purpose of determining the respective breakdown of the two properties over the gait cycle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Magnetic based sample purification]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Continuously Variable Transmission]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:CVT_system.JPG|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This prototype is a proof of concept model of a variable ratio transmission to be implemented in the 2008-2009 Formula SAE competition vehicle.  The gear ratio is determined by the distances between the pulley halves which are controllable electronically.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
[[Image:Team-21-main-picture.JPG|right|thumb|200px]]&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=KhgTNCfdwZw Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|Sweet Baseball Game|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Ballbalancechallenge.JPG|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive game involving ball balancing on a touchscreen with touchscreen feedback and joystick action. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17281</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17281"/>
		<updated>2010-03-17T07:09:02Z</updated>

		<summary type="html">&lt;p&gt;EricWest: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17273</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17273"/>
		<updated>2010-03-17T07:02:04Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Tilt switches - Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Wrist sensor mfth.JPG|thumb|200px|Wrist tilt sensor. Ankles are similar, with a larger strap.]]&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Shoulder sensors mfth.JPG|thumb|200px|Shoulder straps containing the tilt sensors.]]&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Shoulder_sensors_mfth.JPG&amp;diff=17272</id>
		<title>File:Shoulder sensors mfth.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Shoulder_sensors_mfth.JPG&amp;diff=17272"/>
		<updated>2010-03-17T07:00:13Z</updated>

		<summary type="html">&lt;p&gt;EricWest: Shoulder sensors for the Music from the Heart project.  Two tilt switches are attached to the left and right shoulders.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Shoulder sensors for the Music from the Heart project.  Two tilt switches are attached to the left and right shoulders.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Wrist_sensor_mfth.JPG&amp;diff=17266</id>
		<title>File:Wrist sensor mfth.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Wrist_sensor_mfth.JPG&amp;diff=17266"/>
		<updated>2010-03-17T06:56:55Z</updated>

		<summary type="html">&lt;p&gt;EricWest: Wrist tilt sensor the music suit for Music from the Heart.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Wrist tilt sensor the music suit for Music from the Heart.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17262</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17262"/>
		<updated>2010-03-17T06:52:03Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
For a video demonstration, click [http://www.youtube.com/watch?v=YyipByy7m6I here].&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17247</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17247"/>
		<updated>2010-03-17T06:15:17Z</updated>

		<summary type="html">&lt;p&gt;EricWest: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17246</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17246"/>
		<updated>2010-03-17T06:15:02Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[Image:Mfth team picture.JPG|thumb|200px|From left: Thomas, Eric, James]]&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Mfth_team_picture.JPG&amp;diff=17243</id>
		<title>File:Mfth team picture.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Mfth_team_picture.JPG&amp;diff=17243"/>
		<updated>2010-03-17T06:13:43Z</updated>

		<summary type="html">&lt;p&gt;EricWest: team picture of team 21, with their &amp;quot;Music from the Heart Music Suit.&amp;quot;  ME 333, winter 2010&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;team picture of team 21, with their &amp;quot;Music from the Heart Music Suit.&amp;quot;  ME 333, winter 2010&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17242</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17242"/>
		<updated>2010-03-17T06:10:02Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Heart rate monitor - Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure.&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17241</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17241"/>
		<updated>2010-03-17T06:09:47Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Heart rate monitor - Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure. &lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17240</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17240"/>
		<updated>2010-03-17T06:09:26Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Heart rate monitor - Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heart rate sensor mfth.JPG|thumb|200px|Heart rate sensor with the latex band pulled away so that the emitter-detector is revealed]]&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Heart_rate_sensor_mfth.JPG&amp;diff=17238</id>
		<title>File:Heart rate sensor mfth.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Heart_rate_sensor_mfth.JPG&amp;diff=17238"/>
		<updated>2010-03-17T06:07:59Z</updated>

		<summary type="html">&lt;p&gt;EricWest: Illustrates the mechanical design of the heart rate sensor used in the Music from the Heart Music Suit.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Illustrates the mechanical design of the heart rate sensor used in the Music from the Heart Music Suit.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17229</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17229"/>
		<updated>2010-03-17T04:49:34Z</updated>

		<summary type="html">&lt;p&gt;EricWest: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High-Pass Filter]]&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]]: gain = -470&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low-pass filter]: cutoff frequency = 4.82Hz, gain = -70&lt;br /&gt;
# [http://www.electronics-tutorials.ws/filter/filter_7.html Band-pass filter]: Frequency range = 0.72 to 3.39Hz, inverting gain = -46.8&lt;br /&gt;
# [[Comparators|Comparator]]: output to the PIC pin A14, with pull-up resistor to 3.3V and capacitors to smooth out the signal.&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
The sensor itself was a QRB1114 emitter-detector pair that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE HEART SENSOR&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of 16 gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*16 gauge steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17223</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17223"/>
		<updated>2010-03-17T04:05:37Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Heart rate monitor - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High Pass Filter]] - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]] - gain = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low pass filter] - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Bandpass filter - Frequency range = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [[Comparators|Comparator]] - output to the PIC&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG|thumb|center|900px|Heart rate monitor circuit diagram. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
The sensor itself was a &amp;#039;&amp;#039;&amp;#039;INSERT COMPONENT NAME HERE&amp;#039;&amp;#039;&amp;#039; that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE HEART SENSOR&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of &amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17222</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=17222"/>
		<updated>2010-03-17T04:02:19Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Heart rate monitor - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High Pass Filter]] - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]] - gain = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low pass filter] - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Bandpass filter - Frequency range = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [[Comparators|Comparator]] - output to the PIC&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
[[Image:Heartrate monitor.PNG]]&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
The sensor itself was a &amp;#039;&amp;#039;&amp;#039;INSERT COMPONENT NAME HERE&amp;#039;&amp;#039;&amp;#039; that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE HEART SENSOR&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms. The interrupt does not do the entire driving sequence, it merely flags a variable to start the sequence, which is done in the main loop, as seen in the code below.&lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was triggered by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
Initially, we tried skipping the comparator and sending the analog signal directly into one of the PICs analog inputs. Our intention was to use the fast Fourier transform (FFT) library to try to extract the dominant frequency. Unfortunately, we ran into various problems. First, to get the accuracy we wanted for small frequencies, the sample window had to be very long (10 seconds or more), which made the output lag changes in heart rate. Additionally, the FFT was often &amp;quot;messy&amp;quot;, which messed up our original algorithm of detecting the peak frequency between .5 and 2.5 hz. The system would sometimes randomly switch between very different frequencies, and although it was right most of the time it was enough to make the drum beating sound bad. We also tried algorithms to find the [http://en.wikipedia.org/wiki/Fundamental_frequency fundamental frequency] using the entire FFT (instead of just the .5-2.5 hz range), but this was still unreliable. We considered FFT peak detection algorithms, but they seemed to complex for the time and computing power we had available. Because of all this, we went with the simple comparator in the end.&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L298N.pdf|L298 H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
[[Image:T21_motorckt_png.PNG|thumb|center|600px|Motor Circuit (non-motor PIC connections not shown). Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of &amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T21_musicckt_png.PNG|thumb|center|600px|Music circuit diagram. The summing amplifier is not shown. Click for larger image.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
To download the entire C file, click [[Media:Main_music.c|here]]. Below, the file is split into sections for comments.&lt;br /&gt;
&lt;br /&gt;
 /**********************************************************&lt;br /&gt;
  * main_music.c: Main c file for &amp;quot;Music Suit&amp;quot; project&lt;br /&gt;
  *    &lt;br /&gt;
  *    Thomas Peterson, James Rein, Eric West&lt;br /&gt;
  *    ME333 Winter 2010&lt;br /&gt;
  **********************************************************/&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;HardwareProfile.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;delays.c&amp;gt;  //Delayms and Delayus functions&lt;br /&gt;
&lt;br /&gt;
The first section defines all the input and output pins, used with the motor, sensor, and music circuits.&lt;br /&gt;
&lt;br /&gt;
 ////////////////////////////////////////////////////&lt;br /&gt;
 //Pin Defines&lt;br /&gt;
 &lt;br /&gt;
 //YMZ Chip selects&lt;br /&gt;
 #define CS1 LATCbits.LATC2&lt;br /&gt;
 #define CS2 LATCbits.LATC3&lt;br /&gt;
 #define CS3 LATCbits.LATC4&lt;br /&gt;
 #define CS4 LATGbits.LATG6&lt;br /&gt;
 //YMZ communication pins&lt;br /&gt;
 #define NWR LATBbits.LATB0 //&amp;quot;Not WRite&amp;quot;: active low write line&lt;br /&gt;
 #define A0  LATBbits.LATB6 //Address 0&lt;br /&gt;
 #define NIC LATCbits.LATC1 //&amp;quot;Not Input Clear&amp;quot;: active low reset line&lt;br /&gt;
 //YMZ data pins&lt;br /&gt;
 #define D0 LATGbits.LATG9&lt;br /&gt;
 #define D1 LATEbits.LATE8&lt;br /&gt;
 #define D2 LATEbits.LATE9&lt;br /&gt;
 #define D3 LATBbits.LATB5&lt;br /&gt;
 #define D4 LATBbits.LATB4&lt;br /&gt;
 #define D5 LATBbits.LATB3&lt;br /&gt;
 #define D6 LATBbits.LATB2&lt;br /&gt;
 #define D7 LATBbits.LATB1&lt;br /&gt;
 &lt;br /&gt;
 //Tilt inputs&lt;br /&gt;
 #define ENC PORTDbits.RD3&lt;br /&gt;
 #define END PORTDbits.RD2&lt;br /&gt;
 #define ENE PORTDbits.RD1&lt;br /&gt;
 #define ENG PORTCbits.RC14&lt;br /&gt;
 #define ENA PORTCbits.RC13&lt;br /&gt;
 #define ENC5 PORTDbits.RD0&lt;br /&gt;
 &lt;br /&gt;
 //Motor outputs&lt;br /&gt;
 #define IN1 LATBbits.LATB7&lt;br /&gt;
 #define IN2 LATAbits.LATA9&lt;br /&gt;
 #define EN   LATAbits.LATA10&lt;br /&gt;
 &lt;br /&gt;
 ///////////////////////////////////////&lt;br /&gt;
 //Other defines&lt;br /&gt;
 //Motor times&lt;br /&gt;
 #define MS(x) x*312.5&lt;br /&gt;
 #define DRIVETIME MS(100)&lt;br /&gt;
 #define BACKTIME MS(75)&lt;br /&gt;
 #define WAITTIME MS(150)&lt;br /&gt;
 //Channels&lt;br /&gt;
 #define CHNA 1&lt;br /&gt;
 #define CHNB 2&lt;br /&gt;
 #define CHNC 4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 //////////////////////////////////////////&lt;br /&gt;
 //Function definitions&lt;br /&gt;
 void write_chip(int address, int data);&lt;br /&gt;
 void portout(int byte);&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state);&lt;br /&gt;
 //Global variables&lt;br /&gt;
 int mixer1, mixer2;&lt;br /&gt;
 int motorflag = 0;&lt;br /&gt;
The initialization function sets up various parts of the system.&lt;br /&gt;
 /* init() : This function runs initializations, setting up the pic and music chips */&lt;br /&gt;
 void init() {&lt;br /&gt;
    int pbClk = SYSTEMConfigPerformance(SYS_FREQ);&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup inputs / outputs&lt;br /&gt;
    AD1PCFG = 0xFFFF; //All digital inputs&lt;br /&gt;
    TRISG &amp;amp;= 0xFDBF;  //sets G9,G6 to 0 (output); all else remains the same&lt;br /&gt;
    TRISC &amp;amp;= 0xFFE1;  //sets C4,C3,C2,C1 to 0s (outputs); all else remains the same&lt;br /&gt;
    TRISB &amp;amp;= 0xFF80;  //sets B0-B6 0 (output)&lt;br /&gt;
    TRISE &amp;amp;= 0xFCFF;  //sets E8,9 to output&lt;br /&gt;
    TRISB |= 0xF000;  //sets B12,B13,B14,B15 to 1s (inputs); all else remains the same&lt;br /&gt;
    TRISC |= 0x6000;  //sets C14,13 to inputs&lt;br /&gt;
    TRISD |= 0x000F;  //Sets D0,D1,D2,D3 to inputs&lt;br /&gt;
    TRISDbits.TRISD4 = 0; //Output for clock&lt;br /&gt;
    //Motor outputs&lt;br /&gt;
    TRISAbits.TRISA9 = 0;&lt;br /&gt;
    TRISAbits.TRISA10 = 0;&lt;br /&gt;
    TRISBbits.TRISB7 = 0;&lt;br /&gt;
    //Pulse inputs   &lt;br /&gt;
    TRISAbits.TRISA14 = 1;&lt;br /&gt;
    TRISAbits.TRISA15 = 1;&lt;br /&gt;
    //ODC setup&lt;br /&gt;
    ODCCbits.ODCC1 = 1; //open drain control; can only float high (when set high) or pull low &lt;br /&gt;
    &lt;br /&gt;
    /* Initialize outputs */&lt;br /&gt;
    //YMZs&lt;br /&gt;
    CS1 = 1;&lt;br /&gt;
    CS2 = 1;&lt;br /&gt;
    CS3 = 1;&lt;br /&gt;
    CS4 = 1;&lt;br /&gt;
    NWR = 1;&lt;br /&gt;
    A0 = 0;&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    //Motor&lt;br /&gt;
    IN2 = 0;&lt;br /&gt;
    IN1 = 0;&lt;br /&gt;
    EN = 0;&lt;br /&gt;
    &lt;br /&gt;
    Delayms(100);  //wait for power supply to ramp up&lt;br /&gt;
    NIC = 0;       //resets YMZ284s&lt;br /&gt;
    Delayms(10);&lt;br /&gt;
    NIC = 1;&lt;br /&gt;
    &lt;br /&gt;
In the init() function, the pic writes all the setup data to the music chips. This includes the frequency registers, which determine the frequency of each output, the mixer, which determines which channels are on or off (1 = off), and the volume registers, which determine the volume of each channel. After the setup, the only register that is changed in normal operation is the mixer register, which merely turns channels on and off.&lt;br /&gt;
    //////////////////////////////////////////////////&lt;br /&gt;
    //Setup music chips&lt;br /&gt;
    //Setup Chip 1//&lt;br /&gt;
    CS1 = 0;&lt;br /&gt;
    write_chip(0x00,0xC7); //a low               // C4&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x98); //b low               // D&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0x6E); //c low&lt;br /&gt;
    write_chip(0x05,0x01); //c high               // E&lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS1=1;&lt;br /&gt;
    //Setup Chip 2//&lt;br /&gt;
    CS2 = 0;&lt;br /&gt;
    write_chip(0x00,0x2C); //a low               //G 392&lt;br /&gt;
    write_chip(0x01,0x01); //a high&lt;br /&gt;
    write_chip(0x02,0x0D); //b low               //A 440&lt;br /&gt;
    write_chip(0x03,0x01); //b high&lt;br /&gt;
    write_chip(0x04,0xE3); //c low               //C5 523.25&lt;br /&gt;
    write_chip(0x05,0x00); //c high               &lt;br /&gt;
    write_chip(0x07,0xFF); //mixer (0 enables)&lt;br /&gt;
    write_chip(0x08, 0x0A);  //level (volume) A&lt;br /&gt;
    write_chip(0x09, 0x0A);  //level (volume) B&lt;br /&gt;
    write_chip(0x0A, 0x0A);  //level (volume) C&lt;br /&gt;
    CS2=1;&lt;br /&gt;
 &lt;br /&gt;
    mixer1=0xFF;&lt;br /&gt;
    mixer2=0xFF;&lt;br /&gt;
OC5 is used to create a PWM signal with 50% duty at 4Mhz, in effect creating a 4Mhz square wave. This is used by the music chips as a master clock.&lt;br /&gt;
    //////////////////////////////////////////////&lt;br /&gt;
    //Setup OC to create master clock for music chips (~4 Mhz)&lt;br /&gt;
    OpenOC5( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
    OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 20);&lt;br /&gt;
    SetDCOC5PWM(10);&lt;br /&gt;
The interrupts are used, as mentioned above, to control when the motor is driven. The motor should drive once every rising edge.&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT3 (A14)&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
    mINT3IntEnable(1);&lt;br /&gt;
    mINT3SetIntPriority(6);&lt;br /&gt;
    mINT3SetEdgeMode(1); //Rising edge&lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //External interrupt setups (for motor) - INT4 (A15)&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
    mINT4IntEnable(1);&lt;br /&gt;
    mINT4SetIntPriority(5);&lt;br /&gt;
    mINT4SetEdgeMode(0); //Falling edge&lt;br /&gt;
    INTEnableSystemMultiVectoredInt();&lt;br /&gt;
 &lt;br /&gt;
    /////////////////////////////////////////////&lt;br /&gt;
    //Setup motor timer (used for timing delays)&lt;br /&gt;
    OpenTimer3(T3_ON | T3_PS_1_256 | T3_SOURCE_INT, 0xFFFF);&lt;br /&gt;
    ConfigIntTimer3(T3_INT_OFF);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
Main function&lt;br /&gt;
 /* Main function */&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
    init();      /* Run initialization functions */&lt;br /&gt;
    Delayms(1);&lt;br /&gt;
 &lt;br /&gt;
    /* Main while loop: loop indefinietly */&lt;br /&gt;
    while (1) {&lt;br /&gt;
In the main while loop, the PIC checks every cycle to see if an input has changed since the last cycle. Since the &amp;quot;mixer&amp;quot; variables store the current state, if an input does not match up with its valid mixer bit then it has changed recently. In this case, the channelSw() function is called to switch on or off the music channel controlled by that bit.&lt;br /&gt;
       //Check for state changes in music notes&lt;br /&gt;
       if (ENC != (mixer1 &amp;amp; 0x01)) { channelSw(1,CHNA,&amp;amp;mixer1,!ENC); }   //If input ENC (enable C) is not equal to the state of channel A1 (note c), change the state&lt;br /&gt;
       if (END != (mixer1 &amp;amp; 0x02)) { channelSw(1,CHNB,&amp;amp;mixer1,!END); }&lt;br /&gt;
       if (ENE != (mixer1 &amp;amp; 0x04)) { channelSw(1,CHNC,&amp;amp;mixer1,!ENE); }&lt;br /&gt;
       if (ENG != (mixer2 &amp;amp; 0x01)) { channelSw(2,CHNA,&amp;amp;mixer2,!ENG); }&lt;br /&gt;
       if (ENA != (mixer2 &amp;amp; 0x02)) { channelSw(2,CHNB,&amp;amp;mixer2,!ENA); }&lt;br /&gt;
       if (ENC5 != (mixer2 &amp;amp; 0x04)) { channelSw(2,CHNC,&amp;amp;mixer2,!ENC5); }&lt;br /&gt;
During the main while loop, the motor flag variable is checked to see if the motor should be driven. If so, it enters a sequence where it uses timer3 to determine the current stage in the motor cycle, changing the outputs as needed.&lt;br /&gt;
       //Check for motor state changes&lt;br /&gt;
       switch (motorflag) {&lt;br /&gt;
          case 0: break;   //Do nothing (motor off)&lt;br /&gt;
          case 1:   //Start motor cycle&lt;br /&gt;
                WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                IN1 = 0;          //Set H bridge to forward drive&lt;br /&gt;
                IN2 = 1;&lt;br /&gt;
                EN = 1;&lt;br /&gt;
                motorflag = 2;    //In drivedown cycle&lt;br /&gt;
                break;&lt;br /&gt;
          case 2:   //Drivedown cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; DRIVETIME) {  //Wait for DRIVETIME to pass&lt;br /&gt;
                   WriteTimer3(0); //Reset timer to 0&lt;br /&gt;
                   motorflag = 3; //In driveup phase&lt;br /&gt;
                   IN2 = 0;       //Switch H bridge&lt;br /&gt;
                   IN1 = 1;&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 3:   //Driveup cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; BACKTIME) {   //Wait for BACKTIME to pass&lt;br /&gt;
                   WriteTimer3(0);   //Reset timer to 0&lt;br /&gt;
                   motorflag = 4;    //In coast/wait phase&lt;br /&gt;
                   EN = 0;           //Turn off motor&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 4: //coast / wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 5; //more wait&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 5:  //Additional wait cycle&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   //Done!&lt;br /&gt;
                   motorflag = 0; //Motor off (can now be triggered again)&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          //Static wait cycles&lt;br /&gt;
          case 6:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 7; &lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 7:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   WriteTimer3(0);&lt;br /&gt;
                   motorflag = 8; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
          case 8:&lt;br /&gt;
                if (ReadTimer3() &amp;gt; WAITTIME) {&lt;br /&gt;
                   motorflag = 0; &lt;br /&gt;
                }&lt;br /&gt;
                break;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       Delayms(10);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
 }//end main&lt;br /&gt;
 &lt;br /&gt;
Write chip function, which is a support function that writes data to the music chips.&lt;br /&gt;
 /* write_chip: This writes the given byte &amp;quot;data&amp;quot; to the &amp;quot;address&amp;quot; (0 or 1)&lt;br /&gt;
                on a YMZ284. It is assumed that the chip select is already low */&lt;br /&gt;
 void write_chip(int address,int data) {&lt;br /&gt;
    //Write address&lt;br /&gt;
    portout(address);&lt;br /&gt;
    A0 = 0;     //select address mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //Write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //Write cycle end&lt;br /&gt;
   &lt;br /&gt;
    //Write  data&lt;br /&gt;
    portout(data);&lt;br /&gt;
    A0 = 1;     //select data mode&lt;br /&gt;
    Delayus(1); //setup time&lt;br /&gt;
    NWR = 0;    //write cycle begin&lt;br /&gt;
    Delayus(1); //hold time&lt;br /&gt;
    NWR = 1;    //write cycle end&lt;br /&gt;
 }&lt;br /&gt;
Port out function&lt;br /&gt;
 /* port_out: This function outputs a byte to the D0-D7 port */&lt;br /&gt;
 void portout(int byte) {&lt;br /&gt;
    // Note:  !! converts an integer expression to a boolean (1 or 0).&lt;br /&gt;
     D0 = !!(byte  &amp;amp; 1);&lt;br /&gt;
     D1 = !!(byte  &amp;amp; 2); &lt;br /&gt;
     D2 = !!(byte  &amp;amp; 4);   &lt;br /&gt;
     D3 = !!(byte  &amp;amp; 8);&lt;br /&gt;
     D4 = !!(byte  &amp;amp; 16);&lt;br /&gt;
     D5 = !!(byte  &amp;amp; 32); &lt;br /&gt;
     D6 = !!(byte  &amp;amp; 64);   &lt;br /&gt;
     D7 = !!(byte  &amp;amp; 128);&lt;br /&gt;
 }&lt;br /&gt;
Channel switch function, which writes a new mixer value to turn a channel on or off.&lt;br /&gt;
 /* channelSw: Generic channel switch function &lt;br /&gt;
               This writes a new mixer value to chip &amp;quot;chip&amp;quot;. The mixer value&lt;br /&gt;
               depends on &amp;quot;chn&amp;quot;, the channel turning on or off, &amp;quot;state&amp;quot; whether&lt;br /&gt;
               the channel is turning on or off, and &amp;quot;*mixer&amp;quot;, a pointer to&lt;br /&gt;
               the old mixer value. */&lt;br /&gt;
 void channelSw(int chip, int chn, int *mixer, int state) {&lt;br /&gt;
    /* Enable music chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 0; break;&lt;br /&gt;
       case 2: CS2 = 0; break;&lt;br /&gt;
       case 3: CS3 = 0; break;&lt;br /&gt;
       case 4: CS4 = 0; break;&lt;br /&gt;
    }&lt;br /&gt;
    /* Write mixer value */&lt;br /&gt;
    /* This writes to channel 7 (mixer channel) the _new_ mixer value, which is&lt;br /&gt;
       the old mixer value with a particular bit flipped based on &amp;quot;chn&amp;quot; and &amp;quot;state&amp;quot; */&lt;br /&gt;
    write_chip(0x07, (*mixer) = state ? (*mixer) &amp;amp; (0xFF &amp;amp; ~chn) : (*mixer) | chn);&lt;br /&gt;
    /* Disable chip */&lt;br /&gt;
    switch(chip) {&lt;br /&gt;
       case 1: CS1 = 1; break;&lt;br /&gt;
       case 2: CS2 = 1; break;&lt;br /&gt;
       case 3: CS3 = 1; break;&lt;br /&gt;
       case 4: CS4 = 1; break;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
Interrupt functions&lt;br /&gt;
 //External interrupt for motor driving&lt;br /&gt;
 void __ISR(_EXTERNAL_3_VECTOR, ipl6) _SingleVectorHandler(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       motorflag = 1;   //Start motor cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT3ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //External interrupt for motor waiting&lt;br /&gt;
 void __ISR(_EXTERNAL_4_VECTOR, ipl5) _SingleVectorHandler2(void) {&lt;br /&gt;
    if (motorflag == 0) {&lt;br /&gt;
       WriteTimer3(0);&lt;br /&gt;
       motorflag = 6;   //Start wait cycle&lt;br /&gt;
    }&lt;br /&gt;
    //If on already, do nothing&lt;br /&gt;
    mINT4ClearIntFlag();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Heartrate_monitor.PNG&amp;diff=17221</id>
		<title>File:Heartrate monitor.PNG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Heartrate_monitor.PNG&amp;diff=17221"/>
		<updated>2010-03-17T04:01:53Z</updated>

		<summary type="html">&lt;p&gt;EricWest: heart rate monitor circuit diagram for the Music Suit.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;heart rate monitor circuit diagram for the Music Suit.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Heartrate_monitor.JPG&amp;diff=17220</id>
		<title>File:Heartrate monitor.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Heartrate_monitor.JPG&amp;diff=17220"/>
		<updated>2010-03-17T03:58:36Z</updated>

		<summary type="html">&lt;p&gt;EricWest: Heartrate monitor circuit for Music Suit.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Heartrate monitor circuit for Music Suit.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16888</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16888"/>
		<updated>2010-03-16T09:32:29Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Subsystems */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into three subsystems: heart rate monitor, drum actuation, and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High Pass Filter]] - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]] - gain = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low pass filter] - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Bandpass filter - Frequency range = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [[Comparators|Comparator]] - output to the PIC&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
The sensor itself was a &amp;#039;&amp;#039;&amp;#039;INSERT COMPONENT NAME HERE&amp;#039;&amp;#039;&amp;#039; that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE HEART SENSOR&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms.  &lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was trigged by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;TALK ABOUT TRYING FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L293D.pdf|L293D H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM OF H-BRIDGE AND PIC INTERFACE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of &amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM OF YMZs ATTACHED TO THE PIC AND THE SUMMING CIRCUIT&amp;#039;&amp;#039;&amp;#039;, unless we feel the link in the mechatronics wiki is sufficient to describe the summing circuit.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16887</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16887"/>
		<updated>2010-03-16T09:23:35Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Heart rate monitor - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into two subsystems: drum heart rate and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# [[Passive Filters#High-Pass Filter (HPF)|Passive High Pass Filter]] - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [[Operational Amplifiers (Op-Amps)#Inverting Amplifier|Inverting Amplifier]] - gain = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [http://en.wikipedia.org/wiki/Low-pass_filter#Active_electronic_realization Active Low pass filter] - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Bandpass filter - Frequency range = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# [[Comparators|Comparator]] - output to the PIC&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
The sensor itself was a &amp;#039;&amp;#039;&amp;#039;INSERT COMPONENT NAME HERE&amp;#039;&amp;#039;&amp;#039; that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE HEART SENSOR&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms.  &lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was trigged by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;TALK ABOUT TRYING FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L293D.pdf|L293D H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM OF H-BRIDGE AND PIC INTERFACE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of &amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM OF YMZs ATTACHED TO THE PIC AND THE SUMMING CIRCUIT&amp;#039;&amp;#039;&amp;#039;, unless we feel the link in the mechatronics wiki is sufficient to describe the summing circuit.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16886</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16886"/>
		<updated>2010-03-16T09:12:55Z</updated>

		<summary type="html">&lt;p&gt;EricWest: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into two subsystems: drum heart rate and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor - Concepts==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Electrical Design===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# Passive high pass filter - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Inverting amplifier - gain = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Active Low pass filter - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Bandpass filter - Frequency range = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Comparator - output to the PIC&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
===Heart rate monitor - Mechanical Design===&lt;br /&gt;
&lt;br /&gt;
The sensor itself was a &amp;#039;&amp;#039;&amp;#039;INSERT COMPONENT NAME HERE&amp;#039;&amp;#039;&amp;#039; that was encased in open-cell foam insulation.  We inserted it into the foam by drilling and filing a hole in the foam to the appropriate size, and gluing the sensor in place.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE HEART SENSOR&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drum actuator - Electrical design==&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms.  &lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was trigged by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;TALK ABOUT TRYING FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L293D.pdf|L293D H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM OF H-BRIDGE AND PIC INTERFACE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
====Drum actuator - Mechanical Design====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of &amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Music Tones - Electrical Design==&lt;br /&gt;
The music tones were activated by tilt switches and generated using a [http://pdf1.alldatasheet.com/datasheet-pdf/view/82065/YAMAHA/YMZ284.html YMZ284] chip and were output through a 1/8&amp;quot; jack to a standard set of computer speakers.&lt;br /&gt;
&lt;br /&gt;
Each YMZ284 is capable of producing and mixing any combination of three tones.  Since we wanted to have six notes from a [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale], we needed two of these chips and used an [[Operational Amplifiers (Op-Amps)#Summer|summing opamp circuit]] to combine outputs from each chip.  We envisioned a possibility of adding [http://en.wikipedia.org/wiki/Overtone overtones] to each note, to make them sound better and more like a  real instrument, so we ended up having four YMZ284s attached to our board.  When we tried adding an overtone an octave above the fundamental frequency, it ended up sounding harsh and whiny.  We decided the tones sounded better with no overtones, so we are only using 2 of the 4 chips on our board. &lt;br /&gt;
&lt;br /&gt;
The YMZ284 communicates with the PIC over an 8-bit databus, plus additional pins for chip select, address, write enable, and reset.  All four of our YMZ284s shared all of their pins &amp;#039;&amp;#039;except&amp;#039;&amp;#039; the chip select line; each required their own individual chip select line so that the PIC could specify with which chips it wanted to talk.  The circuit diagram below shows how the chips were connected to the PIC and the summing circuit that followed.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM OF YMZs ATTACHED TO THE PIC AND THE SUMMING CIRCUIT&amp;#039;&amp;#039;&amp;#039;, unless we feel the link in the mechatronics wiki is sufficient to describe the summing circuit.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Electrical Design===&lt;br /&gt;
In order to detect when the limbs of the user had moved past a certain critical angle, we chose to use tilt switches.  We purchased our tilt switches for $2 each from [http://www.goldmine-elec-products.com/prodinfo.asp?number=G16881 Electronics Goldmine].  We chose to use tilt switches instead of an accelerometer because the switches were much cheaper and we figured they would be easier to work with. &lt;br /&gt;
&lt;br /&gt;
The tilt switches we chose are optically-based with an emitter and detector that are selectively blocked by a small ball.  When the critical angle is achieved, the tiny ball rolls up a ramp, allowing the emitter to shine directly on the detector, and current flows.  When the angle is neutral, the ramp forces the ball to block the light, making current stop flowing through the phototransistor.  The &amp;quot;ramp&amp;quot; is really an inverted cone, so the switch can be activated by a change in angle in any direction away from the neutral position.  We purchased three different tilt switches to try, each with a different critical angle - 15, 30, and 45 degrees.  The configuration we ended up using was: &lt;br /&gt;
&lt;br /&gt;
*30 degrees for shoulders and ankles&lt;br /&gt;
*45 degrees for elbows&lt;br /&gt;
&lt;br /&gt;
In hindsight, we would have used all 45-degree switches because they produced the sharpest jump from off to on.  The 15-degree switches were practically unusable because they created a large amount of noise as they switched on and off.  &lt;br /&gt;
&lt;br /&gt;
We used the tilt switches to provide high-low inputs to the PIC to tell it when to turn on any of the six tones.  By attaching these switches to the body such that they are in the neutral position when the body is relaxed, we were able to control the six tones by moving the body in relatively natural ways.  &lt;br /&gt;
&lt;br /&gt;
===Tilt switches - Mechanical Design===&lt;br /&gt;
The switches were attached to the user&amp;#039;s body using adjustable straps and buckles.  The wrist and ankle sensors were simply a loop of webbing with an adjustable buckle attached.  The straps could be tightened or loosened to fit any size user.  To attach the switch to the straps, we created an enclosure for each switch out of high-density foam (left over scraps from DSGN 307).  The switch was jammed into a hole in the foam so that it could not easily be moved.  The foam was then taped to the straps using electrical tape.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE WRIST AND ANKLE STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The shoulder straps were a bit more involved.  Two loops with buckles, similar to the wrist and ankle straps, went over the user&amp;#039;s shoulder and underneath their armpit.  To keep these straps from sliding off the shoulders,  a large strap across the user&amp;#039;s back connected the two smaller straps together.  This large strap was also used for mounting the solder board which gathered the wires from all six tilt switches and sent them to the PIC over one ribbon cable.  Using this strap configuration, we found that the user could comfortably and securely wear the sensors.  &lt;br /&gt;
&lt;br /&gt;
To attach the switches to the shoulders, we again created a foam encasement.  However, electrical tape was not secure enough to hold the foam pieces to the irregularly-shaped shoulder straps.  Instead, we riveted a piece of canvas to the webbing straps.  We chose to use rivets instead of sewing because the sewing machine could not tightly sew the foam encasement in place.  With rivets, we were able to pull the canvas tightly around the foam so that it couldn&amp;#039;t move.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE SHOULDER STRAPS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=Results= &lt;br /&gt;
&lt;br /&gt;
The project turned out to be a mild success overall.  The tilt switches worked very well for activating the music tones, but the heart rate monitor was less successful.  One of the biggest issues was getting rid of very low frequency drift in the signal that made the peaks sometimes as high as 10V, but other times less 1V.  Dealing with this fluctuation in peak size was the most difficult part of signal processing.  As mentioned above, we tried FFT in order to establish a steady heart rate, but could not get the resolution we desired, thus we abandoned the idea.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;PROBABLY NEED MORE TECHNICAL RESULTS HERE, BUT I&amp;#039;M NOT SURE WHAT TO SAY RIGHT NOW&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The best result was that using the device was just plain fun.  We each had a great time moving around and hearing the fun sounds that resulted, or if we were feeling ambitious, we would try to play a simple melody like &amp;quot;Mary Had a Little Lamb.&amp;quot;  It was rather difficult to play anything more complicated than that because it required lots of body control and precise movements.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reflections=&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Successes&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches activated each of the six notes when they were supposed to&lt;br /&gt;
**the YMZ284 chips were able to produce all six notes at the same time, allowing cool chords&lt;br /&gt;
*tones were in tune and formed fun melodies and chords as the body moved&lt;br /&gt;
*drum actuator hit the drum reliably and with good tone&lt;br /&gt;
*heart rate monitor usually showed clear peaks on a scope, but was finnicky in practice&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Room for improvements&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*tilt switches sometimes bounced, so the beginning, or particularly the ends of the notes sounded jagged&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; add a low pass filter to the switch signal so that the signal ramps up and down.  &lt;br /&gt;
*the shoulder straps sometimes needed adjustments for each individual in order for the sensors to be in the correct position&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; create straps with more constraints, such as a strap across the chest as well as the back, to ensure that the sensors are in the correct positions and orientations. &lt;br /&gt;
*the straps could be easier to put on&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; maybe integrate them into a single garment, like a onesie&lt;br /&gt;
*the heart rate monitor was not reliable.  Low frequency drift made setting a comparison level nearly impossible, especially for more than one specific user.&lt;br /&gt;
**&amp;#039;&amp;#039;Possible Solution:&amp;#039;&amp;#039; improve FFT method so that desired resolution could be achieved in a short sample period (around 10 seconds).  Or implement a complicated peak detection algorithm on the PIC.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;JAMES SHOULD ADD SOME KIND OF HEARTWARMING CONCLUSION CUZ HE&amp;#039;S GOOD AT THAT STUFF&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16854</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16854"/>
		<updated>2010-03-16T01:36:13Z</updated>

		<summary type="html">&lt;p&gt;EricWest: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT TEAM PICTURE HERE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into two subsystems: drum heart rate and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor==&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab  followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
The sensor itself was a &amp;#039;&amp;#039;&amp;#039;INSERT COMPONENT NAME HERE&amp;#039;&amp;#039;&amp;#039; that was encased in open-cell foam insulation.  A round, finger-shaped groove was filed into the foam and the sensor sat flush with the bottom of this groove.  The user&amp;#039;s finger was held in the correct position with relatively constant pressure using a latex band around the finger and the foam enclosure. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF THE HEART SENSOR&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
===Signal processing===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# Passive high pass filter - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Inverting amplifier - gain = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Active Low pass filter - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Bandpass filter - Frequency range = &amp;#039;&amp;#039;&amp;#039;INSERT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Comparator - output to the PIC&lt;br /&gt;
&lt;br /&gt;
The complete signal processing circuit is shown below.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
===Drum beat===&lt;br /&gt;
&lt;br /&gt;
Once the signal from the heart rate sensor is sent to the PIC, the rising edge triggers an interrupt which starts the driving sequence for the motor that strikes the drum.  The drive sequence was: drive down (into drum) 100ms, drive up 75ms, wait 150ms.  &lt;br /&gt;
&lt;br /&gt;
An additional interrupt was triggered by the falling edge of the signal; this falling edge interrupt added additional wait time that prevented the PIC from being &amp;quot;fooled&amp;quot; by a noisy falling edge.  For instance, if the falling signal had some noise in it, the rising edge interrupt would be triggered again, thus causing the drum to strike on both the rising and falling edges of the heartbeat.  We only wanted one strike per heartbeat, so the falling edge interrupt was trigged by the &amp;#039;&amp;#039;first&amp;#039;&amp;#039; falling edge, and any noise in the falling edge was ignored because the PIC was told to wait for 300ms.  With a maximum delay of 150 + 300 = 450ms from the two interrupts, the fastest heartbeat our drum could play was 133 beats per minute, but we did not expect anyone to come play the instrument after running, so this was plenty high for our purposes.  &lt;br /&gt;
&lt;br /&gt;
The motor for driving the drumstick was driven by an [[media:L293D.pdf|L293D H-bridge]].  See [[Driving a high current DC Motor using an H-bridge]] for more information on how this works.  Our particular circuit diagram is shown below: &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT CIRCUIT DIAGRAM OF H-BRIDGE AND PIC INTERFACE&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
====Mechanical Design of Drum Actuator====&lt;br /&gt;
&lt;br /&gt;
We wanted to use a real drum for our drum beat, so our challenge was to attach a motor and drumstick to a drum.  We chose a small rack tom for its resonant tone that is reminiscent of a heart beat.  &lt;br /&gt;
&lt;br /&gt;
To attach the drumstick to the motor shaft, we used a small block of acrylic (.5&amp;quot;x.5&amp;quot;x2&amp;quot;).  The drumstick was cut down to 8&amp;quot; in length so that it would require less torque from the motor.  In one end of the block, a hole was drilled and the drumstick was sanded to the correct diameter in order to snuggly fit into the hole.  To ensure that the drumstick could not slide out of the block, a screw was placed in a hole drilled through both the stick and the block.  The other end of the block was attached to the motor shaft using a split-clamp method: A hole the size of the motor shaft was drilled through the block, and then a slit was cut from the end of the block to the hole, allowing a screw to tightly clamp the block around the motor.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSERT PICTURE OF DRUMSTICK-MOTORSHAFT ATTACHMENT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To attach the motor-stick assembly to the drum, we utilized the tuning screws on the drum.  A sheet metal bracket with holes in the appropriate places attached the motor to two of these tuning screws.  The bracket was easily made by cutting and bending a piece of &amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; gauge steel sheet metal to the appropriate size.  Ideally, this part would have been made out of one continuous piece of sheet metal, but we could not find a large enough sheet available in the shop, so we used rivets to connect two smaller pieces together.  &lt;br /&gt;
&lt;br /&gt;
After testing the drum striking, we decided it was too loud.  To dampen the sound, we taped a piece of foam core and a shop rag to the head of the drum where the stick strikes it.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts list for drum actuator&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Bargain drumstick, at least .5&amp;quot; in diameter&lt;br /&gt;
*Small block of acrylic, .5&amp;quot;x.5&amp;quot;x2&amp;quot; (aluminum would work just as well, this is what was available) &lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;GAUGE&amp;#039;&amp;#039;&amp;#039; steel sheet metal for bracket&lt;br /&gt;
*Screws and nuts&lt;br /&gt;
*Foam core, shop rag, tape for dampening&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16853</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16853"/>
		<updated>2010-03-15T23:51:35Z</updated>

		<summary type="html">&lt;p&gt;EricWest: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Insert team picture here&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Subsystems=&lt;br /&gt;
&lt;br /&gt;
Although intended as a single, cohesive system that would allow the user to intuitively make music, the project was easily divided into two subsystems: drum heart rate and music tones.  Below is more explanation about each subsystem. &lt;br /&gt;
&lt;br /&gt;
==Heart rate monitor==&lt;br /&gt;
&lt;br /&gt;
In brainstorming how to translate a heart beat into a drum beat, we decided that the least intrusive method would be the best.  Attaching electrodes to the user would simplify the process of identifying a heart beat, but attaching the sensors directly to the skin would be a time-consuming and personally-invasive process.  Instead, we decided a finger tip sensor would be much more comfortable and easy to use.  &lt;br /&gt;
&lt;br /&gt;
To make a finger tip sensor, we used the concepts of [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography].  Photoplethysmography is typically used in [http://en.wikipedia.org/wiki/Pulse_oximeter pulse oximeters] and finger-tip sensors in commercially-available devices.  We originally tried to hack a heart rate monitor that we had purchased, but this proved difficult, so we decided to make our own.  &lt;br /&gt;
&lt;br /&gt;
The basic concept of photoplethysmography is that blood reflects a certain amount of IR light, and the blood density in the finger changes as the heart pumps, so the IR reflectivity of the finger changes as the heart beats.  Using an IR emitter-detector pair found in the mechatronics lab (&amp;#039;&amp;#039;&amp;#039;Insert the component name here&amp;#039;&amp;#039;&amp;#039;) followed by lots of amplification and filtering, we were able to obtain a decent signal with peaks when the user&amp;#039;s heart beat.&lt;br /&gt;
&lt;br /&gt;
===Signal processing===&lt;br /&gt;
&lt;br /&gt;
The signal coming directly out of the IR detector was very weak and noisy.  To obtain just the information we desired, we ran it through the following filters and amplifiers: &lt;br /&gt;
&lt;br /&gt;
# Passive Low pass filter - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;Insert&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Inverting amplifier - gain = &amp;#039;&amp;#039;&amp;#039;Insert&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Active Low pass filter - cutoff frequency = &amp;#039;&amp;#039;&amp;#039;Insert&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Bandpass filter - Frequency range = &amp;#039;&amp;#039;&amp;#039;Insert&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Comparator - output to the PIC&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16852</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16852"/>
		<updated>2010-03-15T23:27:21Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
*James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
*Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Insert team picture here&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16851</id>
		<title>Music from the Heart -- Music Suit</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Music_from_the_Heart_--_Music_Suit&amp;diff=16851"/>
		<updated>2010-03-15T23:26:09Z</updated>

		<summary type="html">&lt;p&gt;EricWest: New page: =Introduction=  This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body. Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the [http://en.wikipedia.org/wiki/Pentatonic_scale pentatonic scale]. The heart beat was obtained using [http://en.wikipedia.org/wiki/Photoplethysmograph photoplethysmography] on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
Thomas Peterson (Computer Engineering, 2010)&lt;br /&gt;
James Rein (Biomedical Engineering and Music Cognition, 2010)&lt;br /&gt;
Eric West (Mechanical Engineering, 2011)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Insert team picture here&amp;#039;&amp;#039;&amp;#039;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=16850</id>
		<title>ME 333 final projects</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=16850"/>
		<updated>2010-03-15T23:14:04Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* ME 333 Final Projects 2010 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See the &amp;#039;&amp;#039;&amp;#039;[[ME 333 end of course schedule]]&amp;#039;&amp;#039;&amp;#039;.  &lt;br /&gt;
&lt;br /&gt;
Final projects for ME 333 in years 2000-2007 can be found&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;[http://lims.mech.northwestern.edu/~design/mechatronics/ here]&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2010 ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Sample Project Title]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
You can copy and paste this wiki code to start your wiki page (but don&amp;#039;t erase this code).  Then replace this text with your own.  A few sentences describing what your project does, with a link to a youtube video.  Look at other final project wiki pages for ideas, but see [[ME 333 end of course schedule]] for more information on what should be included on your wiki page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Music from the Heart -- Music Suit]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body.  Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the pentatonic scale.  The heart beat was obtained using photoplethysmography on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Conservation of Angular Momentum Locomotion Robot (Fluffbot)]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
Cute fluffy robot that uses conservation of angular momentum to move forward and backward. The robot&amp;#039;s momentum wheel accelerates in the floor-plane. The robot&amp;#039;s net angular momentum must remain zero-- a steering wheel guides the Fluffbot to accelerate in the opposite direction. This moves the robot forward in a curved path. The momentum wheel and steering wheel then change direction of acceleration. This repeated process moves the Fluffbot forward in a sinusoidal path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Differential Drive Mobile Robot]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
The goal of this project was to create a small differential drive mobile robot that would act as a low cost replacement for the popular E-Puck Robot.  The robot uses hybrid stepper motors to allow it to track its position through odometry, has a laser cut acrylic chassis for easy replication and replacement, and a 1500 mAh, 13.2V battery pack for long run time.  The robot also uses the NU32 board for its control logic and a XBee chip for communication.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ferrofluid Art Display]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Place holder text for caption .|right]]&lt;br /&gt;
&lt;br /&gt;
A little blurb about our Ferrofluid Art Display will go here. Just a few sentences talking about blah blah lkasjdfal hfalsdjh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Can Launching Fridge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:27_Fridge.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
The goal of the can launching fridge was to create a fridge that would, when initiated by either a remote control or a wired push button, automatically load, aim, and fire a can to multiple predetermined locations. The fridge uses a combination of stepper motors, a DC motor, and solenoids to create the ultimate mix of convenience, fun, and refreshment. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[High Speed Motor Control]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:2dofArmSetUp.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
The project suggested was to design a system for high speed motor control using the PIC 32. To demonstrate the motor control, a two degree of freedom (2-DOF) parallelogram robot arm was designed to follow paths specified in a MATLAB gui.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2009 ==&lt;br /&gt;
&lt;br /&gt;
=== [[Mozart&amp;#039;s Right Hand]] ===&lt;br /&gt;
[[Image:mrh_box.JPG|thumb|150px|Mozart&amp;#039;s Right Hand|right]]&lt;br /&gt;
Mozart&amp;#039;s Right Hand is a musical instrument capable of playing two full octaves of the [http://en.wikipedia.org/wiki/Diatonic_scale Diatonic Scale.]  The user wears a glove on his right hand and uses motions of the hand and fingers to create different notes that are played with a speaker.  The pitch of the note is controlled by the orientation of the user&amp;#039;s hand as he rotates it ether from the wrist, the elbow, or the shoulder.  The LCD on the front of the box tells the user the pitch that corresponds to his or her current hand orientation.  When the user touches together his thumb and index finger, the speaker plays the tone.  A [http://www.youtube.com/watch?v=vec-W4QeHQU video] of Mozart&amp;#039;s Right Hand in action is available on YouTube.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Persistence-of-Vision Display]] ===&lt;br /&gt;
[[Image:Persistence of Vison Display|right|thumb|150px]]&lt;br /&gt;
This is a fully customizable display implemented using the concept of Persistence of Vision. User-specified images (and even moving images) were displayed by rotating a column of LEDs at speeds faster than 300rpm. Each individual LED was modeled as a row of pixels. Conversely, the rotational position of the panel of LEDs represented the pixel columns of the display; the time interval and rotational speed determined the width of the pixel columns. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Rock Paper Scissors Machine]] ===&lt;br /&gt;
[[Image:rps whole thing.JPG|thumb|150px|Rock Paper Scissors Machine|right]]&lt;br /&gt;
A machine that will play a fully functioning, intuitive game of [http://en.wikipedia.org/wiki/Rock-paper-scissors Rock/Paper/Scissors] (abbreviated as RPS) with a user. The machine is represented by a human-like hand, capable of seperate and independant wrist, arm, finger and thumb motion. The players&amp;#039; hand goes into a glove equipped with flex sensors, which wirelessly transmits data to the machine based on what the player chose. The machine then reads this data, randomly chooses a throw of its own, and displays what the machine threw, what the human threw, total win/loss/tie info, and winner/loser both on an [http://en.wikipedia.org/wiki/Lcd LCD] screen and in the form of a thumbs up/down/side motion. Video of the machine in action can be found [http://www.youtube.com/watch?v=xbLNBSTTrcE here.]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Three-speaker Chladni Patterns]] ===&lt;br /&gt;
[[Image:chladni_660hz|right|thumb|150px]]&lt;br /&gt;
This project uses three speakers to generate shapes on a circular aluminum plate depending on which frequency the speakers are playing at. Once the speakers hit a resonant frequency of the plate, salt migrates to the nodes (zero amplitude) regions of the plate to form distinct patterns.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Basketball]] ===&lt;br /&gt;
[[Image:Mechatronics2009Bball|right|thumb|150px]]&lt;br /&gt;
This project consists of a throwing arm propelled by a Pittman motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot; A video can be found [http://www.youtube.com/watch?v=Y466dzP-qiY here].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Drummer]] ===&lt;br /&gt;
[[Image:Robot_Drummer.jpg|thumb|400pix|right|Robot Drummer]]&lt;br /&gt;
The Robot Drummer is a device that demonstrates high-speed motor control by being able to drum when given commands.  Through an RS232 cable, Matlab sends commands to a &amp;quot;master&amp;quot; PIC.  The master then sends the commands to two &amp;quot;slave&amp;quot; PICs through I2C communication.  The slaves take the commands and implement PID control of the motors.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Fish Refuge]] ===&lt;br /&gt;
[[Image:Entire Fish Refuge|right|thumb|200px]]&lt;br /&gt;
The automated fish refuge allows for the controlled movement of a fish refuge with the goal of recording specific behavior.  The mechanical design is completely adjustable and allows adjustable degrees of oscillating movement and orientation of the refuge.  The program is primarily in MATLAB for ease of use and the velocity profile can be a sine, square, triangle, or any function that the user inputs. [http://www.youtube.com/watch?v=wGOKujMhN88 Check out the video!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Marionette]] ===&lt;br /&gt;
[[Image: MarionettePicForIntro.JPG|right|thumb]] The Marionette Project focused on using RC Servos to make a puppet that would do a dance with the press of a button.  There were 5 different dances programmed for the marionette, showcasing different styles of movement.  The movement had 2 degrees of freedom thanks to using 5 bar linkages and 2 RC servos for each arm.  Two more RC Servos were used on the back of the marionette to create the appearance of leg movement.  The movements included a Hula dance, Jumping Jacks, and even some moves right out of Saturday Night Fever.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Monkeybot]] ===&lt;br /&gt;
[[Image:monkeybot_pic|thumb|right|200px|Monkeybot]]&lt;br /&gt;
The monkeybot is a swinging robot capable of moving side to side and climbing.  It consists of a two link, double pendulum system with an electro-magnet on each end.  At the pivot is a DC motor, which provides an input torque and allows the swinging system to gain energy and climb.  Check out the video of the monkeybot climbing [http://www.youtube.com/watch?v=TA2VcH_GDJ0 here] and a later brachiation video [http://www.youtube.com/watch?v=0hfwJEVQyeQ&amp;amp;feature=related here].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[PPOD-mini:  6-DOF Shaker]] ===&lt;br /&gt;
[[Image:PPOD_mini.JPG|thumb|200x200 px|right|PPOD-mini 6-DOF Shaker]]&lt;br /&gt;
The PPOD-mini is a miniaturized version of the Programmable Part-feeding Oscillatory Device ([http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm PPOD]) found in the Laboratory for Intelligent Mechanical Systems (LIMS) at Northwestern. The PPOD-mini utilizes six speakers that act like actuators. The speakers are connected to a acrylic plate via flexures of tygon and iron. In its current implementation, the phase of the speakers can be controlled independently, giving the device six degrees of freedom. The movement of objects placed on the acrylic plate can be controlled by changing the phases of the speakers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Xylophone]] ===&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|200x200 px|right|Automated Xylophone]]&lt;br /&gt;
The Automated Xylophone controls several solenoids which hit various pitches on an actual xylophone based on the note selected.  The device has two main modes: using the keypad, a user can choose to either play notes in real time or store songs to be played back later.  A video of the Automated Xylophone playing in real time mode can be found [http://www.youtube.com/watch?v=_ubpAEyq9kg here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vision-based Cannon]] ===&lt;br /&gt;
[[Image:SM_Gun_Camera_PIC_Setup.JPG|thumb|200x200 px|right|Vision-based Cannon]]&lt;br /&gt;
This project uses a webcam and Matlab to analyze an image and direct a modified USB Missile Launcher to fire at targets found in the image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axes, and then tracks the emitter with a laser. [[Media:MT_MS_AZ_TrackerVideo.mp4|See Spot Run.]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This remote control robotic snake uses servo motors with a traveling sine wave motion profile to mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
Featured on [http://blog.makezine.com/archive/2009/03/well_documented_robotic_snake.html Makezine.com].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Programmable Stiffness Joint]] === &lt;br /&gt;
&lt;br /&gt;
[[Image:SteelToePic2.jpg|thumb|200px|The &amp;#039;Steel Toe&amp;#039; programmable stiffness joint|right]]&lt;br /&gt;
&lt;br /&gt;
The Programmable Stiffness Joint varies rotational stiffness as desired by the user.  It is the first step in modeling the mechanical impedance of the human ankle joint (both stiffness and damping) for the purpose of determining the respective breakdown of the two properties over the gait cycle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Magnetic based sample purification]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Continuously Variable Transmission]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:CVT_system.JPG|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This prototype is a proof of concept model of a variable ratio transmission to be implemented in the 2008-2009 Formula SAE competition vehicle.  The gear ratio is determined by the distances between the pulley halves which are controllable electronically.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
[[Image:Team-21-main-picture.JPG|right|thumb|200px]]&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=KhgTNCfdwZw Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|Sweet Baseball Game|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Ballbalancechallenge.JPG|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive game involving ball balancing on a touchscreen with touchscreen feedback and joystick action. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=16849</id>
		<title>ME 333 final projects</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=16849"/>
		<updated>2010-03-15T23:13:38Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* ME 333 Final Projects 2010 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See the &amp;#039;&amp;#039;&amp;#039;[[ME 333 end of course schedule]]&amp;#039;&amp;#039;&amp;#039;.  &lt;br /&gt;
&lt;br /&gt;
Final projects for ME 333 in years 2000-2007 can be found&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;[http://lims.mech.northwestern.edu/~design/mechatronics/ here]&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2010 ==&lt;br /&gt;
&lt;br /&gt;
=== [[Music from the Heart -- Music Suit]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
This project attempted to create a natural form of musical expression by connecting sensors to the body.  Six tilt switches were attached to the wrist, ankles, and shoulders, each controlling a single pitch from the pentatonic scale.  The heart beat was obtained using photoplethysmography on the user&amp;#039;s finger, and this signal was used to strike a drum in sync with the heart beat.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Sample Project Title]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
You can copy and paste this wiki code to start your wiki page (but don&amp;#039;t erase this code).  Then replace this text with your own.  A few sentences describing what your project does, with a link to a youtube video.  Look at other final project wiki pages for ideas, but see [[ME 333 end of course schedule]] for more information on what should be included on your wiki page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Conservation of Angular Momentum Locomotion Robot (Fluffbot)]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
Cute fluffy robot that uses conservation of angular momentum to move forward and backward. The robot&amp;#039;s momentum wheel accelerates in the floor-plane. The robot&amp;#039;s net angular momentum must remain zero-- a steering wheel guides the Fluffbot to accelerate in the opposite direction. This moves the robot forward in a curved path. The momentum wheel and steering wheel then change direction of acceleration. This repeated process moves the Fluffbot forward in a sinusoidal path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Differential Drive Mobile Robot]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
The goal of this project was to create a small differential drive mobile robot that would act as a low cost replacement for the popular E-Puck Robot.  The robot uses hybrid stepper motors to allow it to track its position through odometry, has a laser cut acrylic chassis for easy replication and replacement, and a 1500 mAh, 13.2V battery pack for long run time.  The robot also uses the NU32 board for its control logic and a XBee chip for communication.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ferrofluid Art Display]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Persistence of Vison Display|thumb|150px|Place holder text for caption .|right]]&lt;br /&gt;
&lt;br /&gt;
A little blurb about our Ferrofluid Art Display will go here. Just a few sentences talking about blah blah lkasjdfal hfalsdjh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Can Launching Fridge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:27_Fridge.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
&lt;br /&gt;
The goal of the can launching fridge was to create a fridge that would, when initiated by either a remote control or a wired push button, automatically load, aim, and fire a can to multiple predetermined locations. The fridge uses a combination of stepper motors, a DC motor, and solenoids to create the ultimate mix of convenience, fun, and refreshment. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[High Speed Motor Control]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:2dofArmSetUp.jpg|thumb|150px|Project photo caption.|right]]&lt;br /&gt;
The project suggested was to design a system for high speed motor control using the PIC 32. To demonstrate the motor control, a two degree of freedom (2-DOF) parallelogram robot arm was designed to follow paths specified in a MATLAB gui.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2009 ==&lt;br /&gt;
&lt;br /&gt;
=== [[Mozart&amp;#039;s Right Hand]] ===&lt;br /&gt;
[[Image:mrh_box.JPG|thumb|150px|Mozart&amp;#039;s Right Hand|right]]&lt;br /&gt;
Mozart&amp;#039;s Right Hand is a musical instrument capable of playing two full octaves of the [http://en.wikipedia.org/wiki/Diatonic_scale Diatonic Scale.]  The user wears a glove on his right hand and uses motions of the hand and fingers to create different notes that are played with a speaker.  The pitch of the note is controlled by the orientation of the user&amp;#039;s hand as he rotates it ether from the wrist, the elbow, or the shoulder.  The LCD on the front of the box tells the user the pitch that corresponds to his or her current hand orientation.  When the user touches together his thumb and index finger, the speaker plays the tone.  A [http://www.youtube.com/watch?v=vec-W4QeHQU video] of Mozart&amp;#039;s Right Hand in action is available on YouTube.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Persistence-of-Vision Display]] ===&lt;br /&gt;
[[Image:Persistence of Vison Display|right|thumb|150px]]&lt;br /&gt;
This is a fully customizable display implemented using the concept of Persistence of Vision. User-specified images (and even moving images) were displayed by rotating a column of LEDs at speeds faster than 300rpm. Each individual LED was modeled as a row of pixels. Conversely, the rotational position of the panel of LEDs represented the pixel columns of the display; the time interval and rotational speed determined the width of the pixel columns. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Rock Paper Scissors Machine]] ===&lt;br /&gt;
[[Image:rps whole thing.JPG|thumb|150px|Rock Paper Scissors Machine|right]]&lt;br /&gt;
A machine that will play a fully functioning, intuitive game of [http://en.wikipedia.org/wiki/Rock-paper-scissors Rock/Paper/Scissors] (abbreviated as RPS) with a user. The machine is represented by a human-like hand, capable of seperate and independant wrist, arm, finger and thumb motion. The players&amp;#039; hand goes into a glove equipped with flex sensors, which wirelessly transmits data to the machine based on what the player chose. The machine then reads this data, randomly chooses a throw of its own, and displays what the machine threw, what the human threw, total win/loss/tie info, and winner/loser both on an [http://en.wikipedia.org/wiki/Lcd LCD] screen and in the form of a thumbs up/down/side motion. Video of the machine in action can be found [http://www.youtube.com/watch?v=xbLNBSTTrcE here.]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Three-speaker Chladni Patterns]] ===&lt;br /&gt;
[[Image:chladni_660hz|right|thumb|150px]]&lt;br /&gt;
This project uses three speakers to generate shapes on a circular aluminum plate depending on which frequency the speakers are playing at. Once the speakers hit a resonant frequency of the plate, salt migrates to the nodes (zero amplitude) regions of the plate to form distinct patterns.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Basketball]] ===&lt;br /&gt;
[[Image:Mechatronics2009Bball|right|thumb|150px]]&lt;br /&gt;
This project consists of a throwing arm propelled by a Pittman motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot; A video can be found [http://www.youtube.com/watch?v=Y466dzP-qiY here].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Drummer]] ===&lt;br /&gt;
[[Image:Robot_Drummer.jpg|thumb|400pix|right|Robot Drummer]]&lt;br /&gt;
The Robot Drummer is a device that demonstrates high-speed motor control by being able to drum when given commands.  Through an RS232 cable, Matlab sends commands to a &amp;quot;master&amp;quot; PIC.  The master then sends the commands to two &amp;quot;slave&amp;quot; PICs through I2C communication.  The slaves take the commands and implement PID control of the motors.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Fish Refuge]] ===&lt;br /&gt;
[[Image:Entire Fish Refuge|right|thumb|200px]]&lt;br /&gt;
The automated fish refuge allows for the controlled movement of a fish refuge with the goal of recording specific behavior.  The mechanical design is completely adjustable and allows adjustable degrees of oscillating movement and orientation of the refuge.  The program is primarily in MATLAB for ease of use and the velocity profile can be a sine, square, triangle, or any function that the user inputs. [http://www.youtube.com/watch?v=wGOKujMhN88 Check out the video!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Marionette]] ===&lt;br /&gt;
[[Image: MarionettePicForIntro.JPG|right|thumb]] The Marionette Project focused on using RC Servos to make a puppet that would do a dance with the press of a button.  There were 5 different dances programmed for the marionette, showcasing different styles of movement.  The movement had 2 degrees of freedom thanks to using 5 bar linkages and 2 RC servos for each arm.  Two more RC Servos were used on the back of the marionette to create the appearance of leg movement.  The movements included a Hula dance, Jumping Jacks, and even some moves right out of Saturday Night Fever.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Monkeybot]] ===&lt;br /&gt;
[[Image:monkeybot_pic|thumb|right|200px|Monkeybot]]&lt;br /&gt;
The monkeybot is a swinging robot capable of moving side to side and climbing.  It consists of a two link, double pendulum system with an electro-magnet on each end.  At the pivot is a DC motor, which provides an input torque and allows the swinging system to gain energy and climb.  Check out the video of the monkeybot climbing [http://www.youtube.com/watch?v=TA2VcH_GDJ0 here] and a later brachiation video [http://www.youtube.com/watch?v=0hfwJEVQyeQ&amp;amp;feature=related here].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[PPOD-mini:  6-DOF Shaker]] ===&lt;br /&gt;
[[Image:PPOD_mini.JPG|thumb|200x200 px|right|PPOD-mini 6-DOF Shaker]]&lt;br /&gt;
The PPOD-mini is a miniaturized version of the Programmable Part-feeding Oscillatory Device ([http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm PPOD]) found in the Laboratory for Intelligent Mechanical Systems (LIMS) at Northwestern. The PPOD-mini utilizes six speakers that act like actuators. The speakers are connected to a acrylic plate via flexures of tygon and iron. In its current implementation, the phase of the speakers can be controlled independently, giving the device six degrees of freedom. The movement of objects placed on the acrylic plate can be controlled by changing the phases of the speakers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Xylophone]] ===&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|200x200 px|right|Automated Xylophone]]&lt;br /&gt;
The Automated Xylophone controls several solenoids which hit various pitches on an actual xylophone based on the note selected.  The device has two main modes: using the keypad, a user can choose to either play notes in real time or store songs to be played back later.  A video of the Automated Xylophone playing in real time mode can be found [http://www.youtube.com/watch?v=_ubpAEyq9kg here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vision-based Cannon]] ===&lt;br /&gt;
[[Image:SM_Gun_Camera_PIC_Setup.JPG|thumb|200x200 px|right|Vision-based Cannon]]&lt;br /&gt;
This project uses a webcam and Matlab to analyze an image and direct a modified USB Missile Launcher to fire at targets found in the image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axes, and then tracks the emitter with a laser. [[Media:MT_MS_AZ_TrackerVideo.mp4|See Spot Run.]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This remote control robotic snake uses servo motors with a traveling sine wave motion profile to mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
Featured on [http://blog.makezine.com/archive/2009/03/well_documented_robotic_snake.html Makezine.com].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Programmable Stiffness Joint]] === &lt;br /&gt;
&lt;br /&gt;
[[Image:SteelToePic2.jpg|thumb|200px|The &amp;#039;Steel Toe&amp;#039; programmable stiffness joint|right]]&lt;br /&gt;
&lt;br /&gt;
The Programmable Stiffness Joint varies rotational stiffness as desired by the user.  It is the first step in modeling the mechanical impedance of the human ankle joint (both stiffness and damping) for the purpose of determining the respective breakdown of the two properties over the gait cycle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Magnetic based sample purification]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Continuously Variable Transmission]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:CVT_system.JPG|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This prototype is a proof of concept model of a variable ratio transmission to be implemented in the 2008-2009 Formula SAE competition vehicle.  The gear ratio is determined by the distances between the pulley halves which are controllable electronically.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
[[Image:Team-21-main-picture.JPG|right|thumb|200px]]&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=KhgTNCfdwZw Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|Sweet Baseball Game|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Ballbalancechallenge.JPG|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive game involving ball balancing on a touchscreen with touchscreen feedback and joystick action. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=PIC32MX:_I2C_Communication_between_PIC32s&amp;diff=15592</id>
		<title>PIC32MX: I2C Communication between PIC32s</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=PIC32MX:_I2C_Communication_between_PIC32s&amp;diff=15592"/>
		<updated>2010-02-10T06:47:29Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Do not erase this section!&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Your assignment is to create code that allows two PIC32s to communicate via I2C.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Summarize briefly what the page is about.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
Include a schematic and give any part numbers.  A photo of your circuit is OK, but not as a replacement for a schematic.&lt;br /&gt;
&lt;br /&gt;
[[Image:I2C_circuit.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
Where possible, make it a single piece of well-commented cut-and-pastable code, or at least make each function that way, so others can easily copy it.  Most comments should be in the code itself; outside the code (on the wiki) should only be explanatory comments that are too cumbersome to include in the code.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:I2C_circuit.PNG&amp;diff=15591</id>
		<title>File:I2C circuit.PNG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:I2C_circuit.PNG&amp;diff=15591"/>
		<updated>2010-02-10T06:45:35Z</updated>

		<summary type="html">&lt;p&gt;EricWest: This circuit is for I2C communication between 2 PIC32s.  Two push button switches create digital inputs to the master that indicate which byte of data should be sent from the master to the slave.  The slave then sends this byte back to master.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This circuit is for I2C communication between 2 PIC32s.  Two push button switches create digital inputs to the master that indicate which byte of data should be sent from the master to the slave.  The slave then sends this byte back to master.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=PIC32MX:_SPI_Communication_between_PIC32s&amp;diff=15590</id>
		<title>PIC32MX: SPI Communication between PIC32s</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=PIC32MX:_SPI_Communication_between_PIC32s&amp;diff=15590"/>
		<updated>2010-02-10T06:41:43Z</updated>

		<summary type="html">&lt;p&gt;EricWest: /* Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Do not erase this section!&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Your assignment is to create code that allows two PIC32 boards to communicate with each other via SPI.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
SPI or [http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus Serial Peripheral Interface] is a communication method that was once used to connect devices such as printers, cameras, scanners, etc. to a desktop computer. This function has largely  been taken over by USB, but SPI can still be a useful communication tool for some applications. SPI runs using a master/slave set-up and can run in full duplex mode, meaning that signals can be transmitted between the master and the slave simultaneously. There is no standard communication protocol for SPI.&lt;br /&gt;
&lt;br /&gt;
SPI is still used to control some peripheral devices and has some advantages over [[I2C communication between PICs|I2C]]&amp;#039;&amp;#039;&amp;#039;CHANGE THIS TO OUR I2C PAGE!!&amp;#039;&amp;#039;&amp;#039; (another type of serial data communication). SPI can communicate at much higher data rates than I2C. Furthermore, when multiple slaves are present, SPI requires no addressing to differentiate between these slaves. Compared to parallel buses, SPI has the additional benefit of requiring only simple wiring. However, one disadvantage when compared to I2C is that each slave must have a dedicated slave line.  A slave line is not necessary when only one slave is present.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Peripheral devices that still use SPI:&lt;br /&gt;
&lt;br /&gt;
•	Converters (ADC and DAC)&lt;br /&gt;
&lt;br /&gt;
•	Memories (EEPROM and FLASH)&lt;br /&gt;
&lt;br /&gt;
•	Real Time Clocks (RTC)&lt;br /&gt;
&lt;br /&gt;
•	Sensors (temperature, pressure, etc.)&lt;br /&gt;
&lt;br /&gt;
•	Others (signal mixer, potentiometer, LCD controller, UART, CAN controller, USB controller, amplifier)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Basic Operation&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SPI requires three lines, and the optional slave select, and is therefore often termed the “four wire” serial bus. These four lines are described in the table below.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;2&amp;quot; cellpadding=&amp;quot;3&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Line!! Name!! Description&lt;br /&gt;
|-&lt;br /&gt;
|SCK1||Serial Clock||Output from master&lt;br /&gt;
|-&lt;br /&gt;
|SDO1||Master Output, Slave Input||Output from master&lt;br /&gt;
|-&lt;br /&gt;
|SDI1||Master Input, Slave Output||Output from slave&lt;br /&gt;
|-&lt;br /&gt;
|SS1||Slave Select||Output from master (active low)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The master, as its name suggests, controls all communication. By controlling the clock, the master decides when data is sent and received. Within each clock cycle a full duplex communication is carried out; each side sends and receives one bit of information. Because there is no standard communication protocol, the master can either send data or both send and receive data, depending on the needs of the application. Likewise, the slave can either receive data or both receive and send data back to the master.&lt;br /&gt;
&lt;br /&gt;
Using the “Slave Select” line, the master chooses which slave with which to communicate. Note that more than one slave may be selected, simply by applying a logic low to the desired SS lines, as illustrated in the schematic diagram shown above. If a given slave is not selected (its SS is high) it disregards signals sent by the master. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;References&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://www.totalphase.com/support/articles/article03/ SPI Background](www.totalphase.com)&lt;br /&gt;
&lt;br /&gt;
[http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus SPI Wikipedia Article] (www.wikipedia.org)&lt;br /&gt;
&lt;br /&gt;
[http://www.mct.net/faq/spi.html More Information] (www.mct.net)&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
[[Image:SPI_circuit.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
This code, coupled with the circuit diagram above, sends one of two bytes of data from the master to the slave, and back, so the master can output which byte is sent via [[PIC32MX: RS232|RS232]] communication protocol.   &lt;br /&gt;
&lt;br /&gt;
The data bytes are 0xAA and 0x23.  Slave-LED0 toggles when 0xAA is received from the master, and slave-LED1 toggles when anything else (for example, 0x23) is received from the master.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:SPI_circuit.PNG&amp;diff=15589</id>
		<title>File:SPI circuit.PNG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:SPI_circuit.PNG&amp;diff=15589"/>
		<updated>2010-02-10T06:38:52Z</updated>

		<summary type="html">&lt;p&gt;EricWest: uploaded a new version of &amp;quot;Image:SPI circuit.PNG&amp;quot;: This is the circuit used for SPI communication between two PIC32s. It uses two digital inputs from push button switches to control what byte of data is sent from the master to the slave. Edit: Added t&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is the circuit used for SPI communication between two PIC32s.  It uses two digital inputs from push button switches to control what byte of data is sent from the master to the slave.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:SPI_circuit.PNG&amp;diff=15588</id>
		<title>File:SPI circuit.PNG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:SPI_circuit.PNG&amp;diff=15588"/>
		<updated>2010-02-10T06:33:08Z</updated>

		<summary type="html">&lt;p&gt;EricWest: This is the circuit used for SPI communication between two PIC32s.  It uses two digital inputs from push button switches to control what byte of data is sent from the master to the slave.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is the circuit used for SPI communication between two PIC32s.  It uses two digital inputs from push button switches to control what byte of data is sent from the master to the slave.&lt;/div&gt;</summary>
		<author><name>EricWest</name></author>
	</entry>
</feed>