<?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=JonathanDrake</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=JonathanDrake"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php/Special:Contributions/JonathanDrake"/>
	<updated>2026-05-25T03:47:53Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17837</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17837"/>
		<updated>2010-03-18T22:29:08Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Construction===&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of 1/4&amp;quot; thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.&lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
===Parts List=== &lt;br /&gt;
&lt;br /&gt;
This list is for a 1 speaker, 1 accelerometer setup. Each PIC can theoretically handle 2 speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Low-Pass Filter: 66K resistor, 0.01uF capacitor&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Unity Gain Buffer: [http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=LM741CNFS-ND LM741] general purpose op-amp&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Speaker Amp: [http://www.national.com/ds/LM/LM1875.pdf LM1875] 20W Audio Power Amplifier&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Heat sink: attached to LM1875&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Accelerometer: [http://www.analog.com/en/mems/low-g-accelerometers/adxl325/products/product.html ADXL325] 3-AXIS ±5 G&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Speakers: generic 6 ohm, 2&amp;quot; diameter (INSERT SPEAKER SPECs, link)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Build the Circuit===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17836</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17836"/>
		<updated>2010-03-18T22:25:06Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Parts List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
===Parts List=== &lt;br /&gt;
&lt;br /&gt;
This list is for a 1 speaker, 1 accelerometer setup. Each PIC can theoretically handle 2 speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Low-Pass Filter: 66K resistor, 0.01uF capacitor&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Unity Gain Buffer: [http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=LM741CNFS-ND LM741] general purpose op-amp&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Speaker Amp: [http://www.national.com/ds/LM/LM1875.pdf LM1875] 20W Audio Power Amplifier&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Heat sink: attached to LM1875&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Accelerometer: [http://www.analog.com/en/mems/low-g-accelerometers/adxl325/products/product.html ADXL325] 3-AXIS ±5 G&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Speakers: generic 6 ohm, 2&amp;quot; diameter (INSERT SPEAKER SPECs, link)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Build the Circuit===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17835</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17835"/>
		<updated>2010-03-18T22:24:15Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Parts List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
===Parts List=== &lt;br /&gt;
&lt;br /&gt;
This list is for a 1 speaker, 1 accelerometer setup. Each PIC can theoretically handle 2 speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Low-Pass Filter: 66K resistor, 0.01uF capacitor&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Unity Gain Buffer: [http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=LM741CNFS-ND LM741] general purpose op-amp&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Speaker Amp: [http://www.national.com/ds/LM/LM1875.pdf LM1875] 20W Audio Power Amplifier&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Accelerometer: [http://www.analog.com/en/mems/low-g-accelerometers/adxl325/products/product.html ADXL325] 3-AXIS ±5 G&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Speakers: generic 6 ohm, 2&amp;quot; diameter (INSERT SPEAKER SPECs, link)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Build the Circuit===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17834</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17834"/>
		<updated>2010-03-18T22:23:24Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Parts List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
===Parts List=== &lt;br /&gt;
&lt;br /&gt;
Items with * indicate setup for 1 speaker. Multiply by 6 for full configuration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Low-Pass Filter: 66K resistor, 0.01uF capacitor&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Unity Gain Buffer: [http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=LM741CNFS-ND LM741] general purpose op-amp&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Speaker Amp: [http://www.national.com/ds/LM/LM1875.pdf LM1875] 20W Audio Power Amplifier&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Accelerometer: [http://www.analog.com/en/mems/low-g-accelerometers/adxl325/products/product.html ADXL325] 3-AXIS ±5 G&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Speakers: generic 6 ohm, 2&amp;quot; diameter (INSERT SPEAKER SPECs, link)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Build the Circuit===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17833</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17833"/>
		<updated>2010-03-18T22:22:16Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Parts List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
===Parts List=== &lt;br /&gt;
&lt;br /&gt;
Items with * indicate setup for 1 speaker. Multiply by 6 for full configuration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Low-Pass Filter: 66K resistor, 0.01uF capacitor&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Unity Gain Buffer: [http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=LM741CNFS-ND LM741] general purpose op-amp&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Speaker Amp: [http://www.national.com/ds/LM/LM1875.pdf LM1875] 20W Audio Power Amplifier&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Accelerometer: [http://www.analog.com/en/mems/low-g-accelerometers/adxl325/products/product.html ADXL325] 3-AXIS ±5 G&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Build the Circuit===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17832</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17832"/>
		<updated>2010-03-18T22:19:30Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
===Parts List=== &lt;br /&gt;
&lt;br /&gt;
Items with * indicate setup for 1 speaker. Multiply by 6 for full configuration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Low-Pass Filter: 66K resistor, 0.01uF capacitor&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Unity Gain Buffer: [http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=LM741CNFS-ND LM741] general purpose op-amp&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Build the Circuit===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17831</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17831"/>
		<updated>2010-03-18T22:18:34Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Parts List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
===Parts List=== &lt;br /&gt;
&lt;br /&gt;
Items with * indicate setup for 1 speaker. Multiply by 6 for full configuration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Low-Pass Filter: 66K resistor, 0.01uF capacitor&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Unity Gain Buffer: [http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=LM741CNFS-ND|LM741] general purpose op-amp&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Build the Circuit===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17830</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17830"/>
		<updated>2010-03-18T22:18:14Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Parts List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
===Parts List=== &lt;br /&gt;
&lt;br /&gt;
Items with * indicate setup for 1 speaker. Multiply by 6 for full configuration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Low-Pass Filter: 66K resistor, 0.01uF capacitor&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Unity Gain Buffer: [[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=LM741CNFS-ND|LM741]] general purpose op-amp&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Build the Circuit===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17829</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17829"/>
		<updated>2010-03-18T22:16:40Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
===Parts List=== &lt;br /&gt;
&lt;br /&gt;
Items with * indicate setup for 1 speaker. Multiply by 6 for full configuration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Build the Circuit===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17828</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17828"/>
		<updated>2010-03-18T22:14:46Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
Parts List:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32|NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17827</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17827"/>
		<updated>2010-03-18T22:14:35Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
Parts List:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;PIC32MX460F512L, in [[Introduction_to_the_PIC32 NU32 board]] configuration&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17826</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17826"/>
		<updated>2010-03-18T22:12:58Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17825</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17825"/>
		<updated>2010-03-18T22:12:42Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|thumb|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17824</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17824"/>
		<updated>2010-03-18T22:11:34Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
We successfully tested a single speaker/accelerometer setup. The PIC produced a sine wave, through the LPF, which was filtered by the buffer and amplified before driving the speaker. A test mount included an accelerometer rigidly attached to the oscillating part of the speaker. While the speaker vibrated at a 30Hz frequency, the accelerometer readings were fed into the PIC and compared to the input. The mathematical results, in terms of phase and magnitude, compare fairly accurately with oscilloscope readings. &lt;br /&gt;
&lt;br /&gt;
The 6 speaker amplifier circuit seems to be bogged down by noise and power issues. Operation is buggy at best, and varies considerably when external electronics, like oscilloscope leads, are attached. The current required to drive all 6 speakers at once might also be greater than the available current provided by the 12V boardlet adapter.&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17821</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17821"/>
		<updated>2010-03-18T22:01:34Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17819</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17819"/>
		<updated>2010-03-18T22:01:15Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Results and Reflection */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17818</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17818"/>
		<updated>2010-03-18T21:53:18Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results and Reflection==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=17817</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=17817"/>
		<updated>2010-03-18T21:45:33Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* 6-DOF PPOD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See the &#039;&#039;&#039;[[ME 333 end of course schedule]]&#039;&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
Final projects for ME 333 in years 2000-2007 can be found&lt;br /&gt;
&#039;&#039;&#039;[http://lims.mech.northwestern.edu/~design/mechatronics/ here]&#039;&#039;&#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&#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&#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:Isometric view of Fluffbot guts.jpg|thumb|150px|The Fluffbot without Fluff.|right]]&lt;br /&gt;
&lt;br /&gt;
Cute fluffy robot that uses conservation of angular momentum to move forward and backward. The robot&#039;s momentum wheel accelerates in the floor-plane. The robot&#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|Variable Frequency Electrosense|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:Wiitar.jpg|thumb|150px|Guitar Controlled by a wiimote: The Wiitar!|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:Jd-cr-Assembly.jpg|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;
=== [[Butterfly Rolling Manipulation]] ===&lt;br /&gt;
[[Image:Butterflyteampic.jpg|right|upright=1.3|thumb|Butterfly Project at Mechatronics Fair]]&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=dtYv3qNz_LI here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Haptic Gaming System]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Haptikos.jpg|thumb|150px|Haptic Robot.|right]]&lt;br /&gt;
&lt;br /&gt;
An interactive gaming system  that allows the user to physically feel a virtual world. The player controls the cursor by moving the red joystick. Two games were created to test the feedback system. The first is a side-scroller in which you avoid hitting moving blocks. The second involves feeling out the virtual shape with nothing other than a blue position dot and a blank screen. &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&#039;s Right Hand]] ===&lt;br /&gt;
[[Image:mrh_box.JPG|thumb|150px|Mozart&#039;s Right Hand|right]]&lt;br /&gt;
Mozart&#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&#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&#039;s Right Hand in action is available on YouTube.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&#039;&#039;&#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&#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;
&#039;&#039;&#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&#039;&#039;&#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 &#039;Steel Toe&#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>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17816</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17816"/>
		<updated>2010-03-18T21:08:25Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Image:6amps.jpg|thumb|Six speaker amplification circuits, shown here without attached heatsinks.]]The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:6amps.jpg&amp;diff=17815</id>
		<title>File:6amps.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:6amps.jpg&amp;diff=17815"/>
		<updated>2010-03-18T21:07:15Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17814</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17814"/>
		<updated>2010-03-18T21:06:10Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[mailto:jdrake@u.northwestern.edu Jonathan Drake] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[mailto:ramsey.caitlin@gmail.com Caitlin Ramsey] (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17813</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17813"/>
		<updated>2010-03-18T21:05:18Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using [[PIC32MX:_FFT_of_Analog_Input|Fast Fourier Transform (FFT)]], thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17812</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17812"/>
		<updated>2010-03-18T21:03:36Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17811</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17811"/>
		<updated>2010-03-18T21:03:25Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/ Tom Vose] in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as [[PPOD-mini:_6-DOF_Shaker|Ankur Bakshi, Donald Redding, and Ben Tollberg]] from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17810</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17810"/>
		<updated>2010-03-18T21:00:58Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Assembly.jpg|thumb|PPOD showing acrylic plate, base, horizontal and vertical speakers.]]Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Jd-cr-Assembly.jpg&amp;diff=17809</id>
		<title>File:Jd-cr-Assembly.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Jd-cr-Assembly.jpg&amp;diff=17809"/>
		<updated>2010-03-18T20:59:25Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Assembly.jpg&amp;diff=17808</id>
		<title>File:Assembly.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Assembly.jpg&amp;diff=17808"/>
		<updated>2010-03-18T20:59:02Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17807</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17807"/>
		<updated>2010-03-18T20:58:07Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
(INSERT PHOTO, WHOLE RIG)&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17806</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17806"/>
		<updated>2010-03-18T20:57:58Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
(INSERT PHOTO, WHOLE RIG)&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17804</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17804"/>
		<updated>2010-03-18T20:54:04Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk at key attachment points, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17803</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17803"/>
		<updated>2010-03-18T20:51:32Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. [[media:PPOD.zip|Download the zip file]] containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:PPOD.zip&amp;diff=17801</id>
		<title>File:PPOD.zip</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:PPOD.zip&amp;diff=17801"/>
		<updated>2010-03-18T20:36:39Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17800</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17800"/>
		<updated>2010-03-18T20:34:48Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. (INSERT LINK) Download the zip file containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
===Initialization===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares constants, functions, and variables to initialize the program&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Declares multi-dimensional, real-imaginary matrices to handle sampling and FFT analysis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Initializes UART, Interrupts, LEDs, ADC, PWM, and sampling functionality&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Builds a vector containing PWM duty cycles values (to be referenced later) in sinusoidal form&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Performs a series of matrix operations, showing the steps needed to solve for the transfer function (NOTE: this needs to be completed by a future team)&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Continuous Operation===&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Changes PWM duty cycle with an interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Samples speaker signal input (for feedback) and 3 axes of 1 accelerometer with another interrupt routine, period set by user&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If &amp;quot;User&amp;quot; button pressed, FFT the speaker input, x/y/z axis from accelerometer&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Using FFT results for first harmonic (e.g. 30Hz), compute transfer function from input (speaker sine wave) to x-axis, y-axis, z-axis&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Output data over UART2&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17798</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17798"/>
		<updated>2010-03-18T20:25:53Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;This code operates 1 speaker and reads in 3 axes from 1 accelerometer. It performs several matrix operations on the quest to form a 9x6 transfer function matrix, but it does not fully solve the problem.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main code for the project can be found in the file pwm.c. Other C files include cplx.c, which handles complex number declarations and operations, and matrix.c, which handles matrix operations necessary for the transfer function. (INSERT LINK) Download the zip file containing all necessary project files.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17796</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17796"/>
		<updated>2010-03-18T20:18:43Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* &lt;br /&gt;
	PWM.c&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/** INCLUDES ***************************************************/&lt;br /&gt;
#include &amp;quot;HardwareProfile.h&amp;quot;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
#include &amp;quot;dsplib_dsp.h&amp;quot;&lt;br /&gt;
#include &amp;quot;fftc.h&amp;quot;&lt;br /&gt;
#include &amp;quot;cplx.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Constants **************************************************/&lt;br /&gt;
&lt;br /&gt;
#define TRUE 					1&lt;br /&gt;
#define FALSE					0&lt;br /&gt;
#define DESIRED_BAUDRATE    	(19200)     // The desired BaudRate for RS232&lt;br /&gt;
#define PI						(3.14159265)&lt;br /&gt;
#define N						(64)	 	// number of samples per cycle, ALSO CHANGE LOG2N BELOW!&lt;br /&gt;
#define SAMPLES_PER_FFT			(448)		// multiply N by the number of cycles you want to use in the FFT&lt;br /&gt;
#define fftc 					fft16c64	// from fftc.h, for N = 256 use fft16c256, for N = 1024 use fft16c1024	&lt;br /&gt;
//#define SAMPLE_FREQ 			(7680)		// (freq of wave to generate)*(N, # samples per cycle)&lt;br /&gt;
#define NUM_HARMONICS			(1)&lt;br /&gt;
#define NUM_SPEAKERS			(1)&lt;br /&gt;
#define NUM_ACCEL				(1)&lt;br /&gt;
#define PTS_PER_DUTY			(256)		// set how many times per cycle the duty cycle is changed&lt;br /&gt;
#define INPUT_A15       		PORTAbits.RA15	// digital input, switch for SendRS232Data()&lt;br /&gt;
#define T_MATRIX_ROWS			(3)&lt;br /&gt;
#define T_MATRIX_COLS			(2)&lt;br /&gt;
&lt;br /&gt;
/** Function Declarations **************************************/&lt;br /&gt;
void initADC();&lt;br /&gt;
void initPWM();&lt;br /&gt;
void initPWMinterrupt();&lt;br /&gt;
void initSamplingInterrupt();&lt;br /&gt;
void initUART2(int pbClk);&lt;br /&gt;
void computeFFT(); &lt;br /&gt;
void sendDataRS232();&lt;br /&gt;
void transposeMatrix ();&lt;br /&gt;
void eye(float * matrix, int elements, float scalar);&lt;br /&gt;
void disp(float * matrix, int rows, int cols);&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols);&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize);&lt;br /&gt;
float mV_to_duty(float mV);&lt;br /&gt;
float getMag(float re, float im);&lt;br /&gt;
float getPhase(float re, float im);&lt;br /&gt;
float analog_to_mV(float ai);&lt;br /&gt;
float mV_to_G(float mV);&lt;br /&gt;
float maxG(int b[], int n);&lt;br /&gt;
//void zero_dout();&lt;br /&gt;
&lt;br /&gt;
/** Global Variables *******************************************/&lt;br /&gt;
char uart_buffer[64];&lt;br /&gt;
&lt;br /&gt;
float mr[2][2] = {{0,0},{0,0}};&lt;br /&gt;
&lt;br /&gt;
/*** sine wave related vars ***/&lt;br /&gt;
float freq = 30; 				// sine wave freq, in Hz, to be generated by PWM&lt;br /&gt;
int mVpp = 200;					// mV peak-to-peak &lt;br /&gt;
float p = 0;					// phase angle shift&lt;br /&gt;
int duty_cycles[PTS_PER_DUTY] = {0};	// vector to hold duty cycles&lt;br /&gt;
int sampleIndex = 0; 			// index for duty cycle change &amp;amp; sampling&lt;br /&gt;
int pwmIndex = 0; 				// increments to PTS_PER_DUTY&lt;br /&gt;
//long int freqVector[N]; 		// holds multiples of 1st harmonic&lt;br /&gt;
&lt;br /&gt;
// FFT related vars&lt;br /&gt;
int computeFFTflag = FALSE; 	// indicate that an fft computation has been requested&lt;br /&gt;
int FFT_RUNNING = FALSE;&lt;br /&gt;
int log2N = 6; 					// e.g. log2(256) = 8&lt;br /&gt;
int16c scratch[N]; 				// for FFT function&lt;br /&gt;
int16c dout[N]; 				// holds computed FFT until transmission, to be reused a few times&lt;br /&gt;
&lt;br /&gt;
// Transfer Function vars&lt;br /&gt;
//struct Complex G; // temp. transfer function (tf), single element&lt;br /&gt;
//float G_mag; // temp. tf magnitude&lt;br /&gt;
//float G_phase; // temp. tf phase angle&lt;br /&gt;
struct Complex TF[6][6][NUM_HARMONICS] = {0}; // transfer function matrix&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// speaker signal readings (to be FFT &amp;quot;u&amp;quot;)&lt;br /&gt;
// e.g. speaker[0][]: speaker number #1&lt;br /&gt;
int16c speaker[NUM_SPEAKERS][SAMPLES_PER_FFT];&lt;br /&gt;
&lt;br /&gt;
// accelerometer readings (to be FFT &amp;quot;y&amp;quot;)&lt;br /&gt;
// e.g. accel[0][0][]: accelerometer #1, x-axis&lt;br /&gt;
int16c accel[NUM_ACCEL][3][SAMPLES_PER_FFT]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for speaker loopback input&lt;br /&gt;
struct Complex sFFT[NUM_SPEAKERS][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// single-sided FFT result for accelerometers&lt;br /&gt;
// x&#039;&#039;,y&#039;&#039;,z&#039;&#039;,roll,pitch,yaw; 1 harmonic&lt;br /&gt;
struct Complex aFFT[NUM_ACCEL][3][NUM_HARMONICS]; &lt;br /&gt;
&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*struct Complex testNum;&lt;br /&gt;
struct Complex testDen;&lt;br /&gt;
struct Complex testRes;*/&lt;br /&gt;
&lt;br /&gt;
float graphFFT[3][32];&lt;br /&gt;
&lt;br /&gt;
int max = 0;&lt;br /&gt;
int curr = 0;&lt;br /&gt;
float mV = 0;&lt;br /&gt;
float grav = 0;&lt;br /&gt;
&lt;br /&gt;
/** Main Function **********************************************/&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	int	pbClk,i,j,k;&lt;br /&gt;
	float dt,amp,offset;&lt;br /&gt;
	char RS232_Out_Buffer[64];&lt;br /&gt;
&lt;br /&gt;
	// Set all analog pins to be digital I/O&lt;br /&gt;
	// This line of code only needs to be used if your pins are Analog Input (B port)&lt;br /&gt;
    AD1PCFG = 0xFFFF;&lt;br /&gt;
&lt;br /&gt;
	// set inputs&lt;br /&gt;
	TRISAbits.TRISA15 = 1;&lt;br /&gt;
	TRISBbits.TRISB0 = 1;&lt;br /&gt;
	TRISBbits.TRISB6 = 1;&lt;br /&gt;
	TRISBbits.TRISB7 = 1;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	// Configure the proper PB frequency and the number of wait states&lt;br /&gt;
	pbClk = SYSTEMConfigPerformance(SYS_FREQ); &lt;br /&gt;
	&lt;br /&gt;
	// Allow vector interrupts&lt;br /&gt;
	INTEnableSystemMultiVectoredInt(); 	&lt;br /&gt;
	&lt;br /&gt;
	// initialize functions&lt;br /&gt;
	mInitAllLEDs();&lt;br /&gt;
	initUART2(pbClk);&lt;br /&gt;
	initADC();&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// make sine wave vector&lt;br /&gt;
	dt = 1/freq/PTS_PER_DUTY;&lt;br /&gt;
	//dt = 8.33333e-4;&lt;br /&gt;
	//mVamp = (mV_top-mV_bottom)/2;&lt;br /&gt;
	amp = mV_to_duty(mVpp); // peak-to-peak amplitude of sine wave&lt;br /&gt;
	offset = 2*amp;&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer, &amp;quot;%3.1f %3.1f %3.1f\r\n&amp;quot;, dt, amp, offset);&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	for (i=0; i&amp;lt;PTS_PER_DUTY; i++) {&lt;br /&gt;
		duty_cycles[i] = amp*sin(2*PI*freq*(i*dt)+p)+offset;&lt;br /&gt;
		//sprintf(uart_buffer, &amp;quot;i=%d, %d\r\n&amp;quot;, i, duty_cycles[i]);&lt;br /&gt;
		//putsUART2(uart_buffer);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// zero some vectors&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++) {&lt;br /&gt;
		dout[i].re = 0;&lt;br /&gt;
		dout[i].im = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
	initPWM();&lt;br /&gt;
	initPWMinterrupt();&lt;br /&gt;
	initSamplingInterrupt();&lt;br /&gt;
	mLED_0_Toggle();&lt;br /&gt;
	putsUART2(&amp;quot;\r\n***** SYSTEM INITIALIZED *****\r\n\n&amp;quot;);&lt;br /&gt;
	// end inits&lt;br /&gt;
/*&lt;br /&gt;
	int x = 510;&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%d %3.1f %3.1f\n\r&amp;quot;, x, analog_to_mV(x), mV_to_G(analog_to_mV(x))); &lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
/*&lt;br /&gt;
/*	putsUART2(&amp;quot;\r\n\n TRANSPOSE \r\n&amp;quot;);&lt;br /&gt;
	float M1[3][2] = {{1,2},{3,4},{5,6}};	&lt;br /&gt;
	float M2[2][3];&lt;br /&gt;
	transposeMatrix(M1,M2,3,2);&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r%3.1f %3.1f %3.1f&amp;quot;, M2[0][0], M2[0][1], M2[0][2], M2[1][0], M2[1][1], M2[1][2]);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/	&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** MATRIX MULTIPLICATION TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float a[2][3] = {{1,0,2},{-1,3,1}};&lt;br /&gt;
	float B[3][2] = {{3,1},{2,1},{1,0}};&lt;br /&gt;
	float C[2][2];&lt;br /&gt;
	multiplyMatrix(&amp;amp;a,&amp;amp;B,&amp;amp;C,2,3,3,2);&lt;br /&gt;
	disp(&amp;amp;C,2,2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** INVERSE TEST ***\r\n&amp;quot;);&lt;br /&gt;
	float mat1[2][2] = {{1,2},{3,4}};&lt;br /&gt;
	float mati[2][2];&lt;br /&gt;
	matrix_inverse(&amp;amp;mat1, &amp;amp;mati, 2);&lt;br /&gt;
	disp(&amp;amp;mati, 2, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	float pi = 3.141592654;&lt;br /&gt;
	float th1 = 0;&lt;br /&gt;
	float th2 = 2*pi/3;&lt;br /&gt;
	float th3 = 4*pi/3;&lt;br /&gt;
	float h = -1;&lt;br /&gt;
	float r = 5;&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;Constants:\r\n%3.3f %3.3f %3.3f %3.3f %3.1f %3.1f \r\n\n&amp;quot;, pi, th1, th2, th3, h, r);&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	float A[9][6] = {&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th1),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th1),	0,					r*cosf(th1)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th1),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th2),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th2),	0,					r*cosf(th2)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th2),		0},&lt;br /&gt;
		{1,0,0,	0,				r*sinf(th3),		-h},&lt;br /&gt;
		{0,1,0,	-r*sinf(th3),	0,					r*cosf(th3)},&lt;br /&gt;
		{0,0,1,	h,				-r*cosf(th3),		0}&lt;br /&gt;
		};&lt;br /&gt;
	float rot1[3][3] = {&lt;br /&gt;
		{cosf(th1),		0,		-sinf(th1)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th1),		0,		cosf(th1)}};&lt;br /&gt;
	float rot2[3][3] = {&lt;br /&gt;
		{cosf(th2),		0,		-sinf(th2)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th2),		0,		cosf(th2)}};	&lt;br /&gt;
	float rot3[3][3] = {&lt;br /&gt;
		{cosf(th3),		0,		-sinf(th3)},&lt;br /&gt;
		{0,				1,		0},&lt;br /&gt;
		{sinf(th3),		0,		cosf(th3)}};&lt;br /&gt;
	float b2a1[3][1] = {0,1,0};&lt;br /&gt;
	float b2a2[3][1] = {0,1,0};&lt;br /&gt;
	float b2a3[3][1] = {0,1,0};&lt;br /&gt;
	&lt;br /&gt;
	/**********	BUILD B VECTOR FROM ROTATION, ACCELERATIONS *************/&lt;br /&gt;
	float b_sub[3][1],b[9][1];&lt;br /&gt;
	&lt;br /&gt;
	// build piece from accel#1&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot1,&amp;amp;b2a1,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[0][0] = b_sub[0][0];&lt;br /&gt;
	b[1][0] = b_sub[1][0];&lt;br /&gt;
	b[2][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#2&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot2,&amp;amp;b2a2,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[3][0] = b_sub[0][0];&lt;br /&gt;
	b[4][0] = b_sub[1][0];&lt;br /&gt;
	b[5][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	// build piece from accel#3&lt;br /&gt;
	multiplyMatrix(&amp;amp;rot3,&amp;amp;b2a3,&amp;amp;b_sub,3,3,3,1);&lt;br /&gt;
	b[6][0] = b_sub[0][0];&lt;br /&gt;
	b[7][0] = b_sub[1][0];&lt;br /&gt;
	b[8][0] = b_sub[2][0];&lt;br /&gt;
	//disp(&amp;amp;b_sub, 3, 1);&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** b ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;b, 9, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/**********	CALCULATE X! *************/&lt;br /&gt;
&lt;br /&gt;
	putsUART2(&amp;quot;*** A ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;A, 9, 6);&lt;br /&gt;
&lt;br /&gt;
	// transpose A&lt;br /&gt;
	float At[6][9];&lt;br /&gt;
	transposeMatrix(A,At,9,6); // 9x6 -&amp;gt; 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** At ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;At,6,9);&lt;br /&gt;
&lt;br /&gt;
	// A*At&lt;br /&gt;
	float AxAt[6][6];&lt;br /&gt;
	multiplyMatrix(&amp;amp;A,&amp;amp;At,&amp;amp;AxAt,9,6,6,9); // 9x6 * 6x9 = 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAt,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// invert the product of A*At&lt;br /&gt;
	float AxAtinv[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;AxAt,&amp;amp;AxAtinv,6); // 6x6 -&amp;gt; 6x6&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinv ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinv,6,6);	&lt;br /&gt;
	&lt;br /&gt;
	float crap[6][6] = {{4,0,0,0,0,0},{0,4,0,0,0,0},{0,0,4,0,0,0},{0,0,0,4,0,0},{0,0,0,0,4,0},{0,0,0,0,0,4}};&lt;br /&gt;
	float invcrap[6][6];&lt;br /&gt;
	matrix_inverse(&amp;amp;crap,&amp;amp;invcrap,6);&lt;br /&gt;
	putsUART2(&amp;quot;*** (crap) ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;invcrap,6,6);	&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At&lt;br /&gt;
/*	float AxAtinvxAt[6][9];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinv,&amp;amp;At,&amp;amp;AxAtinvxAt,6,6,6,9); // 6x6 * 6x9 = 6x9&lt;br /&gt;
	putsUART2(&amp;quot;*** AxAtinvxAt ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;AxAtinvxAt,6,9);&lt;br /&gt;
&lt;br /&gt;
	// inv(A*At)*At*b = X&lt;br /&gt;
	float X[6][1];&lt;br /&gt;
	multiplyMatrix(&amp;amp;AxAtinvxAt,&amp;amp;b,&amp;amp;X,6,9,9,1); // 6x9 * 9x1 = 6x1&lt;br /&gt;
	putsUART2(&amp;quot;*** X ***\r\n&amp;quot;);&lt;br /&gt;
	disp(&amp;amp;X,6,1);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	while(1)&lt;br /&gt;
	{&lt;br /&gt;
		if (!swUser) { // if user button is pressed&lt;br /&gt;
			computeFFTflag = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
		if ((computeFFTflag == TRUE) &amp;amp; (sampleIndex == (SAMPLES_PER_FFT-1))) { &lt;br /&gt;
			putsUART2(&amp;quot;\r\nFFT start\r\n&amp;quot;);&lt;br /&gt;
			computeFFT();&lt;br /&gt;
			while(FFT_RUNNING){}&lt;br /&gt;
			sendDataRS232();&lt;br /&gt;
			computeFFTflag = FALSE;&lt;br /&gt;
			putsUART2(&amp;quot;FFT done\r\n\n&amp;quot;);&lt;br /&gt;
		}	&lt;br /&gt;
		if (!INPUT_A15) {&lt;br /&gt;
			sprintf(RS232_Out_Buffer,&amp;quot;maxG= %d %3.1f %3.1f\n\r&amp;quot;, max, analog_to_mV(max), mV_to_G(analog_to_mV(max))); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
			/*for (i=0; i&amp;lt;SAMPLES_PER_FFT; i+=2) {&lt;br /&gt;
				sprintf(RS232_Out_Buffer,&amp;quot;(%d) %d %d %d\n\r&amp;quot;, i, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
				putsUART2(RS232_Out_Buffer);&lt;br /&gt;
			}*/&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	CloseOC1(); // turn off PWM&lt;br /&gt;
&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
&lt;br /&gt;
// PWM interupt code for the timer 4&lt;br /&gt;
void __ISR( _TIMER_4_VECTOR, ipl6) T4Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	&lt;br /&gt;
	// set duty cycle &lt;br /&gt;
	SetDCOC1PWM(duty_cycles[pwmIndex]);&lt;br /&gt;
&lt;br /&gt;
	// at the end of 1 cycle?&lt;br /&gt;
	if (pwmIndex==(PTS_PER_DUTY-1)) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer, &amp;quot;%d %d\r\n&amp;quot;, pwmIndex, duty_cycles[pwmIndex]);&lt;br /&gt;
		//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		mLED_1_Toggle();&lt;br /&gt;
		pwmIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		pwmIndex++;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T4 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// interupt code for the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	char RS232_Out_Buffer[64];	&lt;br /&gt;
	int a,s,axis,ai;&lt;br /&gt;
	ai = 0; // which analog-in pin (start with B0)&lt;br /&gt;
	&lt;br /&gt;
	/****** READ SPEAKER SIGNALS ******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {	&lt;br /&gt;
		speaker[s][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
		speaker[s][sampleIndex].im = 0;&lt;br /&gt;
		ai+=1;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/****** ACCELEROMETERs ******/	&lt;br /&gt;
	for (a=ai; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		for (axis=0; axis&amp;lt;3; axis++) {&lt;br /&gt;
			accel[a][axis][sampleIndex].re = ReadADC10(ai);&lt;br /&gt;
			accel[a][axis][sampleIndex].im = 0;&lt;br /&gt;
			ai+=1;	&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// max g?&lt;br /&gt;
	int curr = accel[0][1][sampleIndex].re;&lt;br /&gt;
	if (curr &amp;gt; max) {&lt;br /&gt;
		max = curr;	&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	// if you have collected SAMPLES_PER_FFT samples, then restart&lt;br /&gt;
	if (sampleIndex==(SAMPLES_PER_FFT-1)) {&lt;br /&gt;
		sampleIndex=0; // reset sampleIndex to start cycle again&lt;br /&gt;
	} else {&lt;br /&gt;
		// increment sampleIndex&lt;br /&gt;
		sampleIndex++;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// clear interrupt flag and exit&lt;br /&gt;
	mT3ClearIntFlag();&lt;br /&gt;
&lt;br /&gt;
} // end T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/** Other Functions ********************************************/&lt;br /&gt;
&lt;br /&gt;
void initADC(void) {&lt;br /&gt;
&lt;br /&gt;
	// configure and enable the ADC&lt;br /&gt;
	CloseADC10();	// ensure the ADC is off before setting the configuration&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
				// Turn module on | output in integer | trigger mode auto | enable  autosample&lt;br /&gt;
	#define PARAM1  ADC_MODULE_ON | ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
			    // ADC ref external    | disable offset test    | enable scan mode | perform 12 samples | use one buffer | use MUXA mode&lt;br /&gt;
	#define PARAM2  ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_ON | ADC_SAMPLES_PER_INT_12 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// 				  use ADC internal clock | set sample time&lt;br /&gt;
	#define PARAM3  ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	#define PARAM4	ENABLE_AN0_ANA | ENABLE_AN1_ANA | ENABLE_AN2_ANA | ENABLE_AN3_ANA | ENABLE_AN4_ANA | ENABLE_AN5_ANA | ENABLE_AN6_ANA | ENABLE_AN7_ANA | ENABLE_AN8_ANA | ENABLE_AN9_ANA | ENABLE_AN10_ANA | ENABLE_AN11_ANA&lt;br /&gt;
&lt;br /&gt;
	// define setup parameters for OpenADC10&lt;br /&gt;
	// do not assign channels to scan&lt;br /&gt;
	// don&#039;t skip channel 1,2,3,4&lt;br /&gt;
	#define PARAM5	SKIP_SCAN_AN12 | SKIP_SCAN_AN13 | SKIP_SCAN_AN14 | SKIP_SCAN_AN15&lt;br /&gt;
&lt;br /&gt;
	// configure&lt;br /&gt;
	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);&lt;br /&gt;
	OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using parameter define above&lt;br /&gt;
&lt;br /&gt;
	EnableADC10(); // Enable the ADC&lt;br /&gt;
&lt;br /&gt;
	while ( ! mAD1GetIntFlag() ) { } // wait for the first conversion to complete so there will be valid data in ADC result registers&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWM(void)&lt;br /&gt;
{&lt;br /&gt;
	// init OC1 module, on pin D0&lt;br /&gt;
	OpenOC1( OC_ON | OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE, 0, 0);&lt;br /&gt;
	&lt;br /&gt;
	// init Timer2 mode and period PR2...&lt;br /&gt;
	// if set for 30Hz, PR=41666=0xA2C2, Pre = 64&lt;br /&gt;
	// if set for 20kHz, PR=3999=0x0F9F, Pre = 1&lt;br /&gt;
	OpenTimer2( T2_ON | T2_PS_1_1 | T2_SOURCE_INT, 0x0F9F); // every 1/20000 seconds&lt;br /&gt;
	&lt;br /&gt;
	SetDCOC1PWM(0);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initPWMinterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	OpenTimer4( T4_ON | T4_PS_1_1 | T4_SOURCE_INT, 0x28B0); // every 1/freq/PTS_PER_DUTY seconds&lt;br /&gt;
	mT4SetIntPriority( 6);&lt;br /&gt;
	mT4ClearIntFlag();&lt;br /&gt;
	mT4IntEnable( 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initSamplingInterrupt(void)&lt;br /&gt;
{&lt;br /&gt;
	// init Timer3 mode and period (PR3)&lt;br /&gt;
	OpenTimer3( T3_ON | T3_PS_1_1 | T3_SOURCE_INT, 0xA2C2); // every 1/freq/N seconds&lt;br /&gt;
	&lt;br /&gt;
	mT3SetIntPriority( 7); 	// set Timer3 Interrupt Priority&lt;br /&gt;
	mT3ClearIntFlag(); 		// clear interrupt flag&lt;br /&gt;
	mT3IntEnable( 1);		// enable timer3 interrupts&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initUART2(int pbClk)&lt;br /&gt;
{&lt;br /&gt;
	 // define setup Configuration 1 for OpenUARTx&lt;br /&gt;
 		// Module Enable &lt;br /&gt;
 		// Work in IDLE mode &lt;br /&gt;
 		// Communication through usual pins &lt;br /&gt;
 		// Disable wake-up &lt;br /&gt;
 		// Loop back disabled &lt;br /&gt;
 		// Input to Capture module from ICx pin &lt;br /&gt;
 		// no parity 8 bit &lt;br /&gt;
 		// 1 stop bit &lt;br /&gt;
 		// IRDA encoder and decoder disabled &lt;br /&gt;
 		// CTS and RTS pins are disabled &lt;br /&gt;
 		// UxRX idle state is &#039;1&#039; &lt;br /&gt;
 		// 16x baud clock - normal speed&lt;br /&gt;
 	#define config1 	UART_EN | UART_IDLE_CON | UART_RX_TX | UART_DIS_WAKE | UART_DIS_LOOPBACK | UART_DIS_ABAUD | UART_NO_PAR_8BIT | UART_1STOPBIT | UART_IRDA_DIS | UART_DIS_BCLK_CTS_RTS| UART_NORMAL_RX | UART_BRGH_SIXTEEN&lt;br /&gt;
	 &lt;br /&gt;
	 // define setup Configuration 2 for OpenUARTx&lt;br /&gt;
	 	// IrDA encoded UxTX idle state is &#039;0&#039;&lt;br /&gt;
	 	// Enable UxRX pin&lt;br /&gt;
	 	// Enable UxTX pin&lt;br /&gt;
	 	// Interrupt on transfer of every character to TSR &lt;br /&gt;
	 	// Interrupt on every char received&lt;br /&gt;
	 	// Disable 9-bit address detect&lt;br /&gt;
	 	// Rx Buffer Over run status bit clear&lt;br /&gt;
	 #define config2		UART_TX_PIN_LOW | UART_RX_ENABLE | UART_TX_ENABLE | UART_INT_TX | UART_INT_RX_CHAR | UART_ADR_DETECT_DIS | UART_RX_OVERRUN_CLEAR	&lt;br /&gt;
 &lt;br /&gt;
 	// Open UART2 with config1 and config2&lt;br /&gt;
 	OpenUART2( config1, config2, pbClk/16/DESIRED_BAUDRATE-1);	// calculate actual BAUD generate value.&lt;br /&gt;
 		&lt;br /&gt;
 	// Configure UART2 RX Interrupt with priority 2&lt;br /&gt;
 	ConfigIntUART2(UART_INT_PR2 | UART_RX_INT_EN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;START 1 1\n\r&amp;quot;); //print START. MATLAB uses this as a start delimiter&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//sprintf(RS232_Out_Buffer,&amp;quot;ROWS=%d\n\r&amp;quot;, N); //print the number of rows, so matlab can make the correct sized buffer&lt;br /&gt;
	//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
	//int limit = SAMPLES_PER_FFT;&lt;br /&gt;
	int limit = 10;&lt;br /&gt;
	for (i=0; i&amp;lt;limit; i++) {&lt;br /&gt;
		//sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d\n\r&amp;quot;, speaker[0][i].re, accel[0][0][i].re, accel[0][1][i].re); &lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%3.1f %3.1f %3.1f\n\r&amp;quot;, graphFFT[0][i], graphFFT[1][i], graphFFT[2][i]); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END 1 1\n\r&amp;quot;); //output end so matlab knows we&#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	int a,i,j,h,s;&lt;br /&gt;
	char RS232_Out_Buffer[64]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	FFT_RUNNING = TRUE;	&lt;br /&gt;
&lt;br /&gt;
	/********	TEST COMPLEX OPERATIONS	********/&lt;br /&gt;
/*	testNum.r = 1;&lt;br /&gt;
	testNum.i = 2;&lt;br /&gt;
	testDen.r = 4;&lt;br /&gt;
	testDen.i = -3;&lt;br /&gt;
	testRes = C_div(testNum,testDen);	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;test: %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, testRes.r, testRes.i, getMag(testRes.r,testRes.i), getPhase(testRes.r,testRes.i));&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/******** 	FFT THE SPEAKER SIGNALS 	*******/&lt;br /&gt;
	for (s=0; s&amp;lt;NUM_SPEAKERS; s++) {&lt;br /&gt;
		mips_fft16(dout, speaker[s], fftc, scratch, log2N); // input: speaker[s], output: dout&lt;br /&gt;
		for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
			graphFFT[0][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			//sprintf(RS232_Out_Buffer,&amp;quot;(S) %d, %d+%d*i, %3.1f\n\r&amp;quot;, i, dout[i].re, dout[i].im, getMag(dout[i].re,dout[i].im)); &lt;br /&gt;
			//putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		}&lt;br /&gt;
		for(h = 1; h&amp;lt;=NUM_HARMONICS; h++) {&lt;br /&gt;
			sFFT[s][h].r = dout[h].re;&lt;br /&gt;
			sFFT[s][h].i = dout[h].im;&lt;br /&gt;
		}&lt;br /&gt;
	/*	sprintf(RS232_Out_Buffer,&amp;quot;speaker#%d, %3.1f+%3.1f*i\n\r&amp;quot;, s, sFFT[s][1].r, sFFT[s][1].i); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	*/&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	/******** 	ACCELEROMETER FFT	*******/&lt;br /&gt;
	for (a=0; a&amp;lt;NUM_ACCEL; a++) {&lt;br /&gt;
		&lt;br /&gt;
		/******** 	x-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==1)) { &lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][0], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[1][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][0][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][0][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, X-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][0][1].r, aFFT[a][0][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	y-axis FFT	*******/&lt;br /&gt;
		if ((a==0)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
			mips_fft16(dout, accel[a][1], fftc, scratch, log2N);&lt;br /&gt;
			for (i=0; i&amp;lt;(N/2); i++) {&lt;br /&gt;
				graphFFT[2][i] = getMag(dout[i].re,dout[i].im);&lt;br /&gt;
			}&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][1][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][1][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Y-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][1][1].r, aFFT[a][1][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		/******** 	z-axis FFT	*******/&lt;br /&gt;
		if ((a==1)|(a==2)) {&lt;br /&gt;
			&lt;br /&gt;
		 	mips_fft16(dout, accel[a][2], fftc, scratch, log2N);&lt;br /&gt;
			for(h = 1; h&amp;lt;=NUM_HARMONICS; h++)&lt;br /&gt;
			{&lt;br /&gt;
				aFFT[a][2][h].r = dout[h].re;&lt;br /&gt;
				aFFT[a][2][h].i = dout[h].im;&lt;br /&gt;
			}&lt;br /&gt;
		/*	sprintf(RS232_Out_Buffer,&amp;quot;accel#%d, Z-axis, %d+%d*i\n\r&amp;quot;, a, aFFT[a][2][1].r, aFFT[a][2][1].i); &lt;br /&gt;
			putsUART2(RS232_Out_Buffer);&lt;br /&gt;
		*/&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	/********	FIND TRANSFER FUNCTIONS	*******/&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	TF[0][0][1] = C_div(aFFT[0][0][1],sFFT[0][1]);	&lt;br /&gt;
	TF[1][0][1] = C_div(aFFT[0][1][1],sFFT[0][1]);&lt;br /&gt;
&lt;br /&gt;
	for(i = 0; i &amp;lt; 2; i++) {	&lt;br /&gt;
		// output: frequency vector, the calculated fft, raw samples&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;TF(%d,0,1): %3.1f+%3.1f*i, mag=%3.1f, phase=%3.1f\n\r&amp;quot;, i, TF[i][0][1].r, TF[i][0][1].i, getMag(TF[i][0][1].r, TF[i][0][1].i), getPhase(TF[i][0][1].r, TF[i][0][1].i));&lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// SHOW MAX G-FORCE&lt;br /&gt;
//	int n = SAMPLES_PER_FFT;&lt;br /&gt;
//	sprintf(RS232_Out_Buffer,&amp;quot;maxG: %3.1f %3.1f\n\r&amp;quot;, maxG(accel[0][0],n), maxG(accel[0][1],n));&lt;br /&gt;
//	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
&lt;br /&gt;
	FFT_RUNNING = FALSE;&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void transposeMatrix (float M1[9][6], float M2[6][9], int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
&lt;br /&gt;
	for ( i = 0; i &amp;lt; rows; i++) {&lt;br /&gt;
		for ( j = 0; j &amp;lt; cols; j++) {&lt;br /&gt;
			M2[j][i] = M1[i][j];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void multiplyMatrix (float * A, float * B, float * C, int aRows, int aCols, int bRows, int bCols)&lt;br /&gt;
{&lt;br /&gt;
	/*	&lt;br /&gt;
		Action:			A*B=C&lt;br /&gt;
		Requirements:	aCols = bRows&lt;br /&gt;
	*/&lt;br /&gt;
		&lt;br /&gt;
	int i, j, k, cCols;&lt;br /&gt;
	cCols = aRows;&lt;br /&gt;
	for (i = 0; i &amp;lt; aRows; i++) {&lt;br /&gt;
		for (j = 0; j &amp;lt; bCols; j++) {&lt;br /&gt;
			C[(cCols*i)+j] = 0;&lt;br /&gt;
			for (k = 0; k &amp;lt; aCols; k++) {&lt;br /&gt;
				C[(cCols*i)+j] += A[(aCols*i)+k]*B[(bCols*k)+j];&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void disp(float * matrix, int rows, int cols) {&lt;br /&gt;
	int i, j;&lt;br /&gt;
	char buff[8];&lt;br /&gt;
	for (i=0; i&amp;lt;rows; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;cols; j++) {&lt;br /&gt;
			sprintf(buff,&amp;quot;%6.3f &amp;quot;, matrix[(cols*i)+j]);&lt;br /&gt;
			putsUART2(buff);&lt;br /&gt;
		}&lt;br /&gt;
		putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	}	&lt;br /&gt;
	putsUART2(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void eye(float * matrix, int elements, float scalar) {&lt;br /&gt;
	int i,j;&lt;br /&gt;
	for (i=0; i&amp;lt;elements; i++) {&lt;br /&gt;
		for (j=0; j&amp;lt;elements; i++) {&lt;br /&gt;
			matrix[(elements*i)+j] = scalar;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void matrix_inverse(float *Min, float *Mout, int actualsize) {&lt;br /&gt;
    /* This function calculates the inverse of a square matrix&lt;br /&gt;
     *&lt;br /&gt;
     * matrix_inverse(double *Min, double *Mout, int actualsize)&lt;br /&gt;
     *&lt;br /&gt;
     * Min : Pointer to Input square Double Matrix&lt;br /&gt;
     * Mout : Pointer to Output (empty) memory space with size of Min&lt;br /&gt;
     * actualsize : The number of rows/columns&lt;br /&gt;
     *&lt;br /&gt;
     * Notes:&lt;br /&gt;
     *  - the matrix must be invertible&lt;br /&gt;
     *  - there&#039;s no pivoting of rows or columns, hence,&lt;br /&gt;
     *        accuracy might not be adequate for your needs.&lt;br /&gt;
     *&lt;br /&gt;
     * Code is rewritten from c++ template code Mike Dinolfo&lt;br /&gt;
     */&lt;br /&gt;
    /* Loop variables */&lt;br /&gt;
    int i, j, k;&lt;br /&gt;
    /* Sum variables */&lt;br /&gt;
    float sum,x;&lt;br /&gt;
    &lt;br /&gt;
    /*  Copy the input matrix to output matrix */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize*actualsize; i++) { Mout[i]=Min[i]; }&lt;br /&gt;
    &lt;br /&gt;
    /* Add small value to diagonal if diagonal is zero */&lt;br /&gt;
    for(i=0; i&amp;lt;actualsize; i++)&lt;br /&gt;
    { &lt;br /&gt;
        j=i*actualsize+i;&lt;br /&gt;
        if((Mout[j]&amp;lt;1e-12)&amp;amp;&amp;amp;(Mout[j]&amp;gt;-1e-12)){ Mout[j]=1e-12; }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Matrix size must be larger than one */&lt;br /&gt;
    if (actualsize &amp;lt;= 1) return;&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++) {&lt;br /&gt;
        Mout[i] /= Mout[0]; /* normalize row 0 */&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    for (i=1; i &amp;lt; actualsize; i++)  {&lt;br /&gt;
        for (j=i; j &amp;lt; actualsize; j++)  { /* do a column of L */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[j*actualsize+k] * Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] -= sum;&lt;br /&gt;
        }&lt;br /&gt;
        if (i == actualsize-1) continue;&lt;br /&gt;
        for (j=i+1; j &amp;lt; actualsize; j++)  {  /* do a row of U */&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for (k = 0; k &amp;lt; i; k++) {&lt;br /&gt;
                sum += Mout[i*actualsize+k]*Mout[k*actualsize+j];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = (Mout[i*actualsize+j]-sum) / Mout[i*actualsize+i];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ )  /* invert L */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            x = 1.0;&lt;br /&gt;
            if ( i != j ) {&lt;br /&gt;
                x = 0.0;&lt;br /&gt;
                for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                    x -= Mout[j*actualsize+k]*Mout[k*actualsize+i];&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = x / Mout[j*actualsize+j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* invert U */ {&lt;br /&gt;
        for ( j = i; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            if ( i == j ) continue;&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = i; k &amp;lt; j; k++ ) {&lt;br /&gt;
                sum += Mout[k*actualsize+j]*( (i==k) ? 1.0 : Mout[i*actualsize+k] );&lt;br /&gt;
            }&lt;br /&gt;
            Mout[i*actualsize+j] = -sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for ( i = 0; i &amp;lt; actualsize; i++ ) /* final inversion */ {&lt;br /&gt;
        for ( j = 0; j &amp;lt; actualsize; j++ )  {&lt;br /&gt;
            sum = 0.0;&lt;br /&gt;
            for ( k = ((i&amp;gt;j)?i:j); k &amp;lt; actualsize; k++ ) {&lt;br /&gt;
                sum += ((j==k)?1.0:Mout[j*actualsize+k])*Mout[k*actualsize+i];&lt;br /&gt;
            }&lt;br /&gt;
            Mout[j*actualsize+i] = sum;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
float mV_to_duty(float mV) {&lt;br /&gt;
	float result = 0.817*mV+40.833;&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getMag(float re, float im) {&lt;br /&gt;
	float mag = sqrtf((re*re)+(im*im));&lt;br /&gt;
	return mag;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float getPhase(float re, float im) {&lt;br /&gt;
	float phase = atanf(im/re);&lt;br /&gt;
	return phase;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float analog_to_mV(float ai) {&lt;br /&gt;
	float r = ai*3300/1023;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float mV_to_G(float mV) {&lt;br /&gt;
	float r = (mV-1650)/174;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float maxG(int b[], int n) {&lt;br /&gt;
	int max = 0;&lt;br /&gt;
	int c;&lt;br /&gt;
	for (c=0; c&amp;lt;n; c++) {&lt;br /&gt;
		if(b[c]&amp;gt;max) {&lt;br /&gt;
			max = b[c];&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	float r = mV_to_G(analog_to_mV(max));&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17795</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17795"/>
		<updated>2010-03-18T20:16:55Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17382</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17382"/>
		<updated>2010-03-17T18:36:05Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17381</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17381"/>
		<updated>2010-03-17T18:32:56Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[[Image:24-Drake-Ramsey.jpg|thumb|left|Jonathan Drake and Caitlin Ramsey]]&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17380</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17380"/>
		<updated>2010-03-17T18:32:43Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[[Image:24-Drake-Ramsey.jpg|thumb|left|Jonathan Drake and Caitlin Ramsey]]&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|frame|left|400px|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17189</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17189"/>
		<updated>2010-03-17T02:53:06Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[[Image:24-Drake-Ramsey.jpg|thumb|left|Jonathan Drake and Caitlin Ramsey]]&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|frame|left|400px|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17188</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17188"/>
		<updated>2010-03-17T02:53:00Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[[Image:24-Drake-Ramsey.jpg|thumb|left|Jonathan Drake and Caitlin Ramsey]]&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|frame|left|400px|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17187</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17187"/>
		<updated>2010-03-17T02:51:52Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
[[Image:24-Drake-Ramsey.jpg|thumb|left|Jonathan Drake and Caitlin Ramsey]]&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|frame|left|400px|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17186</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17186"/>
		<updated>2010-03-17T02:51:04Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:24-Drake-Ramsey.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|frame|left|400px|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:24-Drake-Ramsey.jpg&amp;diff=17185</id>
		<title>File:24-Drake-Ramsey.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:24-Drake-Ramsey.jpg&amp;diff=17185"/>
		<updated>2010-03-17T02:50:49Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17184</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17184"/>
		<updated>2010-03-17T02:49:19Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
INSERT TEAM PICTURE&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg|frame|left|400px|Full schematic, showing PIC, LPF, Buffer, Amplifier, and Accelerometer]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17183</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17183"/>
		<updated>2010-03-17T02:46:11Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
INSERT TEAM PICTURE&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Jd-cr-Full-schematic.jpg]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Jd-cr-Full-schematic.jpg&amp;diff=17182</id>
		<title>File:Jd-cr-Full-schematic.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Jd-cr-Full-schematic.jpg&amp;diff=17182"/>
		<updated>2010-03-17T02:45:50Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17181</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17181"/>
		<updated>2010-03-17T02:44:54Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Circuit Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
INSERT TEAM PICTURE&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
[[Image:jd-cr-full-schematic.jpg]]&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17180</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17180"/>
		<updated>2010-03-17T02:43:38Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of (INSERT LINK?) Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as (INSERT LINK) Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle (INSERT LINK), which, when sent through a low-pass filter (INSERT LINK), forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT) (INSERT LINK), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
INSERT TEAM PICTURE&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
INSERT SYSTEM SCHEMATIC (“big picture”)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17179</id>
		<title>6-DOF PPOD</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=6-DOF_PPOD&amp;diff=17179"/>
		<updated>2010-03-17T02:42:23Z</updated>

		<summary type="html">&lt;p&gt;JonathanDrake: New page: == Overview ==  Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of Tom Vose in the Laboratory for I...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Our work on the portable 6 degree-of-freedom (DOF) programmable part-feeding oscillatory device (PPOD) is based off of the previous work of Tom Vose in the Laboratory for Intelligent Mechanical Systems (LIMS), as well as Ankur Bakshi, Donald Redding, and Ben Tollberg from the previous class. The PPOD is a vibrating table driven by six speakers acting as actuators. The speakers vibrate at specific frequencies and phases to create force patterns on the surface of the disk that are capable of moving small objects on pre-determined paths. Previous versions used MATLAB to control the entire system. &lt;br /&gt;
&lt;br /&gt;
For our project, we attempted to control the speakers and feedback operations using only the NU_PIC32 microcontroller board. The PIC32 periodically varies a pulse width modulation (PWM) duty cycle, which, when sent through a low-pass filter, forms a sinusoidal wave that is amplifies to drive the speakers. Readings from accelerometers mounted on the PPOD are compared with the sinusoidal waves using Fast Fourier Transform (FFT), thus creating a transfer function matrix. This matrix characterizes the relationship between the input and the output of the system, and represents the PPOD’s calibration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Team Members ===&lt;br /&gt;
Jonathan Drake (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
Caitlin Ramsey (Mechanical Engineering, 2010)&amp;lt;br&amp;gt;&lt;br /&gt;
INSERT TEAM PICTURE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
&lt;br /&gt;
There are two main mechanical components to our PPOD—the base and the disk. The base is a 20 inch diameter disk made of ¼” thick acrylic. This is where the speakers and electrical components are attached. There are 3 speakers used for vertical motion and 3, on shelves attached to the disk, used for horizontal motion. The motion of the speakers is transferred to the disk, the vibrating surface, through a series of mechanical connections:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/2&amp;quot; diameter rod is superglued to the interior cavity of the speaker&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;1/4&amp;quot; diameter rod is inserted into a hole in the half inch diameter rod&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Flexible tube is then fitted over the 1/4&amp;quot; rod. On the other end of the flexible rod another small quarter inch rod is inserted&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The smaller quarter inch rod is inserted into rectangles that have a quarter inch hole cut out of the center. The rectangle is then glued to the underside of the disk. &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;The horizontal speakers have an extra piece each, a two inch rectangle that is glued to the disk one half and the rectangle is glue to the side of the rectangle. The flexible tubing allows the disk to move without losing the connection with the speakers.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The accelerometers are attached to 1x1x1 inch cubes of solid acrylic that are glued to the underside of the disk. There are three accelerometers attached to the table. The accelerometer mount side of the cube has four holes drilled into each corner to screw the accelerometer board into place. A notch was milled out of the surface for the solder tips, allowing the accelerometer to be flush with the surface of the cube ensuring an accurate reading.    &lt;br /&gt;
&lt;br /&gt;
The disk is 11.5 inch in diameter cut from quarter inch thick acrylic. The speaker attachments are all 60 degrees apart, alternating between vertical and horizontal speakers. All speakers are attached in a symmetrical pattern ensuring the accuracy of the calibration program and the force patterns on the surface. Acrylic was chosen for all the components because of its workability in the Ford machine shop and for its ability to be glued together quite easily.            &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
== Circuit Design ==&lt;br /&gt;
&lt;br /&gt;
INSERT SYSTEM SCHEMATIC (“big picture”)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
The PIC32 controls the entire system. We will explain the circuit, following the path from PIC to speaker, for one speaker. Theoretically, if our project was extended, 6 speakers would be included, but we concentrated on a proof of concept with one speaker subsystem. We connected an output compare (OC1) pin to a low pass filter (LPF) circuit, which converts the square wave duty cycle of the PWM into a sinusoidal wave. We chose appropriate values for the resistor (66K) and capacitor (0.01uF) that gave us a good resolution and response time compared to the duty cycle period coming from the PWM. The output of the LPF was connected to the non-inverting input of a unity gain buffer, as well as back into an analog input pin (AN0) on the PIC. This simple LM741 opamp conditions the noisy sine wave of the PIC for input into the amplification circuit. We powered this opamp with +/- 12V. The output of the buffer is connected to the input of the audio amplification circuit, designated Vin on the diagram. This chip, the LM1875, is powered with +/- 12V, and has a gain of 20 (modified by a resistor value). To deal with noise, we boosted the capacitors connected across the rails to 1000uF. The output of the audio amp was connected to the positive terminal of the speaker. The negative terminal of the speaker was connected to ground. The accelerometer (again, theoretically 3, but we are explaining 1) is attached to the vibrating table disk, and powered by +3.0V. The X, Y, and Z-axis pins of the accelerometer are connected to analog input pins on the PIC: AN1, AN2, and AN3 respectively. We used a +/- 12V boardlet to power the buffer and amplifier, and the NU32 board’s +3.3V to power the accelerometer.&lt;/div&gt;</summary>
		<author><name>JonathanDrake</name></author>
	</entry>
</feed>