<?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=JamesReynolds</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=JamesReynolds"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php/Special:Contributions/JamesReynolds"/>
	<updated>2026-04-15T15:28:21Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.9</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18028</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18028"/>
		<updated>2010-03-19T06:01:05Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
[[image:Team26-Group Pic.jpg|right|Team 26]]&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Assembly=&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px|thumb|stepper motor circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px|thumb|AD9833 Circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right|thumb|signal amplification circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18027</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18027"/>
		<updated>2010-03-19T06:00:44Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg|right|Team 26]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Assembly=&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px|thumb|stepper motor circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px|thumb|AD9833 Circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right|thumb|signal amplification circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18026</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18026"/>
		<updated>2010-03-19T06:00:21Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg|thumb|right|Team 26]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Assembly=&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px|thumb|stepper motor circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px|thumb|AD9833 Circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right|thumb|signal amplification circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18025</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18025"/>
		<updated>2010-03-19T05:59:56Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg|thumb|right|Team 26]]&lt;br /&gt;
&lt;br /&gt;
=Assembly=&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px|thumb|stepper motor circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px|thumb|AD9833 Circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right|thumb|signal amplification circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18024</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18024"/>
		<updated>2010-03-19T05:59:20Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Assembly=&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px|thumb|stepper motor circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px|thumb|AD9833 Circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right|thumb|signal amplification circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18023</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18023"/>
		<updated>2010-03-19T05:58:36Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Assembly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px|thumb|stepper motor circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px|thumb|AD9833 Circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right|thumb|signal amplification circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18022</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18022"/>
		<updated>2010-03-19T05:56:51Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Signal Amplification/Level Shifting Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px|thumb|stepper motor circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px|thumb|AD9833 Circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right|thumb|signal amplification circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18021</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18021"/>
		<updated>2010-03-19T05:56:26Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Signal Generation Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px|thumb|stepper motor circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px|thumb|AD9833 Circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18019</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18019"/>
		<updated>2010-03-19T05:55:52Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Stepper Motor Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px|thumb|stepper motor circuit]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18014</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18014"/>
		<updated>2010-03-19T05:51:29Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Assembly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Fill the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18013</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18013"/>
		<updated>2010-03-19T05:51:01Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Assembly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18011</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18011"/>
		<updated>2010-03-19T05:48:51Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Assembly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png|thumb|right|Sensor Board hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
**Wire Color Code&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18009</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18009"/>
		<updated>2010-03-19T05:46:47Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Assembly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |150px|thumb|right|sensor hookup]]&lt;br /&gt;
[[image:TR_JP_JP_Stepper_hookup.png|150px|thumb|right|stepper motor hookup]]&lt;br /&gt;
[[image:TR_JP_PP_Switch_hookup.png|150px|thumb|right|limit switch hookup]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
*Wire Color Code&lt;br /&gt;
**Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
**White: ground, plugs into main ground rail on board&lt;br /&gt;
**Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
**Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
**Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
*Power&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18005</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18005"/>
		<updated>2010-03-19T05:38:18Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Linear Actuator */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18004</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18004"/>
		<updated>2010-03-19T05:38:03Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Linear Actuator */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads that the sensor is attached to will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18003</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18003"/>
		<updated>2010-03-19T05:37:32Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Stepper Motor Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right||400px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18001</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=18001"/>
		<updated>2010-03-19T05:36:24Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Stepper Motor Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Stepper_circuit.png&amp;diff=18000</id>
		<title>File:TR JP PP Stepper circuit.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Stepper_circuit.png&amp;diff=18000"/>
		<updated>2010-03-19T05:35:19Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: uploaded a new version of &amp;quot;Image:TR JP PP Stepper circuit.png&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17993</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17993"/>
		<updated>2010-03-19T05:31:50Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Stepper Motor Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP_Stepper_circuit.png]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x L297&lt;br /&gt;
**4x 2N6045&lt;br /&gt;
*Resistors&lt;br /&gt;
**3x 3.3K&lt;br /&gt;
*Diodes&lt;br /&gt;
**8x 1N4001&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Stepper_circuit.png&amp;diff=17992</id>
		<title>File:TR JP PP Stepper circuit.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Stepper_circuit.png&amp;diff=17992"/>
		<updated>2010-03-19T05:31:37Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17989</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17989"/>
		<updated>2010-03-19T05:29:05Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Stepper Motor Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
To drive the linear actuator a unipolar stepper motor is used. The stepper motor circuit takes in two signals from the PIC(Direction &amp;amp; Clock) and rotates the rod a corresponding number of steps.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17985</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17985"/>
		<updated>2010-03-19T05:26:16Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Assembly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by plugging in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17983</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17983"/>
		<updated>2010-03-19T05:25:41Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Linear Actuator */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by pluggin in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
The linear actuator works by twisting a threaded rod. A machined bar with matching threads will move because it is constrained from rotation. This actuator allows precise positioning but is very slow.&lt;br /&gt;
[[image:TR_JP_PP_Actuator.png]]&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Actuator.png&amp;diff=17981</id>
		<title>File:TR JP PP Actuator.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Actuator.png&amp;diff=17981"/>
		<updated>2010-03-19T05:25:16Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17973</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17973"/>
		<updated>2010-03-19T05:22:59Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Electrosense Water Tank */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by pluggin in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
The tank is two feet long by 6 inches wide. It is made of laser cut acrylic and has the actuator built into it&amp;#039;s side walls. &lt;br /&gt;
&lt;br /&gt;
[[image:TR_JP_PP_Tank.png]]&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Tank.png&amp;diff=17972</id>
		<title>File:TR JP PP Tank.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Tank.png&amp;diff=17972"/>
		<updated>2010-03-19T05:22:32Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17970</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17970"/>
		<updated>2010-03-19T05:19:43Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Assembly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Main Components&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*Tank with Actuator/Sensor&lt;br /&gt;
*Circuitry with PIC32&lt;br /&gt;
*PC with processing interfaced&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Steps to setting up&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
[[image:TR_JP_PP_Ribbon_Cable.png |100py]]    [[image:TR_JP_JP_Stepper_hookup.png|100py]]   [[image:TR_JP_PP_Switch_hookup.png|100py]]&lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by pluggin in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
[[image:TR_JP_PP_Sensor_hookup.png]]&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Sensor_hookup.png&amp;diff=17969</id>
		<title>File:TR JP PP Sensor hookup.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Sensor_hookup.png&amp;diff=17969"/>
		<updated>2010-03-19T05:14:34Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Switch_hookup.png&amp;diff=17968</id>
		<title>File:TR JP PP Switch hookup.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Switch_hookup.png&amp;diff=17968"/>
		<updated>2010-03-19T05:13:32Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_JP_Stepper_hookup.png&amp;diff=17967</id>
		<title>File:TR JP JP Stepper hookup.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_JP_Stepper_hookup.png&amp;diff=17967"/>
		<updated>2010-03-19T05:12:23Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Ribbon_Cable.png&amp;diff=17966</id>
		<title>File:TR JP PP Ribbon Cable.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP_Ribbon_Cable.png&amp;diff=17966"/>
		<updated>2010-03-19T05:09:41Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17950</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17950"/>
		<updated>2010-03-19T04:34:29Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Assembly==&lt;br /&gt;
There are three main components to our project \n&lt;br /&gt;
1) Tank with Actuator/Sensor \n&lt;br /&gt;
2) Circuitry with PIC32 \n&lt;br /&gt;
3) PC with processing interface \n&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*To get the project up and running once you have gathered all the parts start by filling the tank with tap water until the level is just above the sensing board. Confirm that there are no leaks with the tank.&lt;br /&gt;
*Hook up the sensors and actuators to the circuitry. &lt;br /&gt;
**The sensor ataches via a grey ribbon cable. The strip should be to the right and facing up on the board.&lt;br /&gt;
**The stepper motor attaches by pluggin in the 8 pin socket on the left hand, bottom side of the breadboard. The black and white wires should be at the top, and should be plugged into the same row on the board as the wires that run to the +12volt supply&lt;br /&gt;
**The limit switches also attach by plugging in an 8 pin socket. This time orientation is not important, but one side of the switch must run to a resistor while the other attaches to ground and the signal out cable(yellow)&lt;br /&gt;
*Build &amp;amp; power the circuitry&lt;br /&gt;
**The sensor circuit is built on a solder board to ensure good conections between components. This board is attached to the solderless breadboard via 5 wires&lt;br /&gt;
***Red: +5 volt supply. Plugs into same row as read wire running from supply on left hand side of board&lt;br /&gt;
***White: ground, plugs into main ground rail on board&lt;br /&gt;
***Black: -5 volt supply. Plugs into output of -5 volt regulator chip.&lt;br /&gt;
***Green: sensor input. Plugs into row on breadboard that contains output from AD9833 amp as well as input to PIC&lt;br /&gt;
***Blue: sensor output: plugs into blue wire on breadboard that runs into PIC&lt;br /&gt;
**Power to the motor is from the 12volt regulator chip located at the top, left hand side of the breadboard&lt;br /&gt;
**Power to the PIC is from the USB cable&lt;br /&gt;
*Hook up PIC to PC&lt;br /&gt;
**USB cable for power&lt;br /&gt;
**RS232 cable for communication (ensure that the proper drivers are installed)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and emitter/sensor board, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17792</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17792"/>
		<updated>2010-03-18T19:26:04Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Motor Control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
The Stepper motor circuit requires two inputs:&lt;br /&gt;
*Direction pin- D2 on the PIC&lt;br /&gt;
*Clock Signal- D1 on the PIC&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17788</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17788"/>
		<updated>2010-03-18T19:23:35Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* AD9833 Chip control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers was more reliable. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17787</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17787"/>
		<updated>2010-03-18T19:23:19Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* AD9833 Chip control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 is supposed to function under SPI control, however we found that bit-banging the registers worked better. The chip requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the voltage sine wave values for the emitted wave (512 points), the voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17785</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17785"/>
		<updated>2010-03-18T19:21:12Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* PIC Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS 2011&lt;br /&gt;
*Joshua Peng, BME 2017&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
==Stepper Motor Circuit==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:team26-ad9833.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
The PIC completes 5 main tasks:&lt;br /&gt;
*controls the AD9833 chip to generate voltage sinusoids&lt;br /&gt;
*receives the emitted and received waves and generates values corresponding to the analog signals such that each sinusoid period is 16 points long for each of the 19 frequencies&lt;br /&gt;
*calculates the FFT of the emitted and received waves&lt;br /&gt;
*controls the motor and linear actuator&lt;br /&gt;
*sends data to the PC (Processing) via RS232&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Media:PIC_electrosense.zip |Download the full version of PIC code]]&lt;br /&gt;
&lt;br /&gt;
===AD9833 Chip control===&lt;br /&gt;
&lt;br /&gt;
AD9833 requires 16 binary bits for its input. The ad9833_set_freq(int value[]) function will send an array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  This process is performed for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of the SCLK signal.  Therefore, we set the FSYNC pin to low only when we are sending SDATA bits.  Also, we initially set the SCLK pin to high and then set it back to low right after we send out SDATA. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an AD9833 chip, we need to reset the chip and send certain control bits to configure the type of wave that will be sent out.  Then, we send the lsb and msb of the frequency register value.  This value will be saved in the frequency register of the chip and will be used to calculate the actual frequency of the output wave.  Next, we have to &amp;quot;un-reset&amp;quot; the chip.  This function will generate sine waves if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHz. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on the AD9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
===Receiving Waves and Calculating Sampling Frequencies===&lt;br /&gt;
&lt;br /&gt;
We will read in two different sine waves from the analog inputs B4 and B5. &lt;br /&gt;
* B4: Emitted wave&lt;br /&gt;
* B5: Received wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitted wave and received wave.  The sampling frequency of the timer is calculated to produce 16 points in one period of the sine wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100Hz to 10KHz.  With the PR value equation from Lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to the PR values we calculated for each sampling frequency.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each input frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Input Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===FFT===&lt;br /&gt;
&lt;br /&gt;
A good FFT reference and explanation is found [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// timer 3 interrupt&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motor Control===&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communication with Processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was a &amp;quot;receive&amp;quot; interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor move an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop motor movement&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor moves forward until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor moves in reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerates the motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slows down the motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends data to Processing for further calculation and plotting&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to the zero position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The code below is the infinite while loop in the main() function of our code.&lt;br /&gt;
In order to move the sensor a half inch, our stepper motor will proceed through 1288 steps.  After 1288 steps, the motor will stop moving and it will start to read in and send data.  After it sends data to Processing, the motor will start to move again.  If the stepper motor clock pulse periods are decreased, the motor will move faster.  We control the motor speed with Delayms(speed).  If &amp;#039;speed&amp;#039; (&amp;#039;speed&amp;#039; is an integer variable) is incremented, then the motor slows down and if &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Sending Data to the PC (Processing)===&lt;br /&gt;
We send 6 variables out to the PC (Processing) via RS232.  We send out the frequency array (256 points and 256 zeros) that holds the frequency values used in the FFT, the analog voltage sine wave values for the emitted wave (512 points), the analog voltage sine wave values for the received wave (512 points), the real component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), the imaginary component of the complex result of the FFT of the emitted wave (first 256 points) and received wave (last 256 points), and &amp;#039;halfinch&amp;#039; which is an integer that counts how many half inches the motor has moved forward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[[Media:PIC_electrosense.zip |Full version of PIC code]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Processing==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link below and at the end of this section to a zip file with the actual code with comments.  Some important portions of code are posted underneath their descriptions.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int kk = 0;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int L = 512;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;int finish;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
counts the number of halfinches the emitter/sensor board has moved forward starting from the zero position&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float bx = width/3; | float by = height/3;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
all the buttons and plots are laid out in the window using these 2 variables&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float magnitude; | float phase;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
there are several ways that we are calculating magnitude and phase (as you can see with magnitude_pic, abs_phase, etc.).  The value set to &amp;quot;magnitude&amp;quot; and &amp;quot;phase&amp;quot; are the actual, final magnitude and phase we plot and record.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;float[] freq2 = new float[19];&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
later on in the code, this array is set to hold the 19 expected frequencies (100, 200, 300,...,8000, 9000, 10000) to compare with the actual frequencies of the emitted and received waves calculated using the FFT in the PIC.&lt;br /&gt;
&lt;br /&gt;
The setup() function basically creates rectangles in which plot curves appear, initializes the font used, sets the frame rate, initializes the output text write, and initializes the controlP5 buttons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
  &lt;br /&gt;
  //First, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
       &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude_pic,&amp;quot; &amp;quot;magnitude_pic2,&amp;quot; &amp;quot;phase_pic,&amp;quot; and &amp;quot;phase_pic2&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;magnitude_wave,&amp;quot; and &amp;quot;phase_wave&amp;quot; are calculated from looking at the sine waves &lt;br /&gt;
  //(magnitude_wave = peak divided by peak, phase_wave = visually inspecting zero point to zero point distance)&lt;br /&gt;
  magnitude_wave = max(nsin2)/max(nsin1);&lt;br /&gt;
  magnitude_pic = sqrt((fftreal2[b]*fftreal2[b])+(fftimag2[b]*fftimag2[b]))/&lt;br /&gt;
                  sqrt((fftreal1[a]*fftreal1[a])+(fftimag1[a]*fftimag1[a]));&lt;br /&gt;
  magnitude_pic2 = max2/max1;&lt;br /&gt;
  phase_wave = (b2-a2)/u2*360;&lt;br /&gt;
  phase_pic = (atan2(fftimag2[b],fftreal2[b])-atan2(fftimag1[a],fftreal1[a]))*180/PI;&lt;br /&gt;
  phase_pic2 = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  &lt;br /&gt;
  //what we chose to use for the final value for &amp;quot;magnitude&amp;quot; and &amp;quot;phase,&amp;quot; &lt;br /&gt;
  //we felt these two methods of calculating the magnitude and phase gave us the most consistent values&lt;br /&gt;
  magnitude = magnitude_pic2;&lt;br /&gt;
  phase = phase_wave;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-objects.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the emitter/detector board directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
[[Image:team26-dom.gif | 350px]]  [[Image:team26-dop.gif | 350px]]&lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank underneath the center of the board approximately at these specifications.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diffobjects.jpg | 350px]]  [[Image:team26-diffobjects2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 350px]]  [[Image:team26-middlep.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the board is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank such that the center of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass.jpg | 350px]]  [[Image:team26-brass2.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the board moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 350px]]  [[Image:team26-shiftp.GIF | 350px]]&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the board is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank shifted from the midline such that the detector electrodes on the underside of the board would pass over the brass cylinder.&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-brass_shifted.jpg | 350px]]  [[Image:team26-brass_shifted3.jpg | 350px]]&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=17524</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=17524"/>
		<updated>2010-03-18T01:26:06Z</updated>

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

		<summary type="html">&lt;p&gt;JamesReynolds: /* Signal Amplification/Level Shifting Circuit - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS&lt;br /&gt;
*Joshua Peng, BME&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Concept Overview=&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
== Stepper Motor Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:TR JP PP-AD9833 Pic.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AD9833 Chip control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
AD9833 requires 16 binary bits for its input. Ad9833_set_freq(int value[]) function will send the array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  And do this job for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of SCLK signal.  Therefor we set the FSYNC pin is low only when we are sending SDATA bits.  Also, we set the SCLK pin to high initially and set it back to low right after we send the SDATA. &amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an ad9833 chip, we need to reset the chip and send a control bits to setup the type of wave. Then, we send lsb and msb of frequency register value, this value will saved in frequency register of the chip and will use it to calculate the actual frequency of the output wave. And then we have to un-reset the chip. This function does all this job for generating sine wave if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHZ. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on ad9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Receiving Waves&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We will read two different sin waves from analog input B4 and B5. &lt;br /&gt;
* B4: Emitter wave&lt;br /&gt;
* B5: Receiver wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitter wave and receiver wave.  The sampling frequency of the timer is determined so it can actually reads 16 points in one cycle of the sin wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100HZ to 10KHZ.  With the PR value equation from lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to PR values we calculated for each sampling frequencies.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each reading frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Reading Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Good references and explanation for FFT calculation can be found in [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// interrupt the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Control Motor&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communicating with processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was receive interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor moves an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop the motor move&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor move forwards until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor move reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerate the speed of motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slow down the speed of motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends all the data to plot graphs in the processing&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to initial position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The codes below is the infinite while loop in main function of our code.&lt;br /&gt;
In order to move the sensor for a half inch 1288 steps are required for stepper motor.  So after 1288 steps, the motor will stop moving and it will start to read data.  After it sends data to processing, the motor start to move again.  For the stepper motor, if we generate the clock with shorter period will make the motor moves faster. So we are controlling the motor speed with Delayms(speed).  If the &amp;#039;speed&amp;#039; incremented, then the motor slows down and if the &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Send to processing&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[http://hades.mech.northwestern.edu/images/3/3c/Main.c Full version of C code]&lt;br /&gt;
&lt;br /&gt;
==Processing Code==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link here and at the end of this section to a zip file with the actual code with comments.  Some of the more important functions are posted.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*int kk = 0; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*int L = 512; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void calc()&lt;br /&gt;
{&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
        &lt;br /&gt;
  //first, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after (on the right side of) &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude,&amp;quot; &amp;quot;abs_phase,&amp;quot; and &amp;quot;phase_pic&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;wave_mag,&amp;quot; &amp;quot;phase&amp;quot; and &amp;quot;phase_u2&amp;quot; are calculated from looking at the sine waves&lt;br /&gt;
  //unfortunately, magnitude_pic wouldn&amp;#039;t work anyway since the &amp;quot;i (or j)&amp;quot; is eliminated, &lt;br /&gt;
  //the imaginary component would just combine with the real component when added in the transfer function. &lt;br /&gt;
  &lt;br /&gt;
  magnitude = max2/max1;&lt;br /&gt;
  abs_phase = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  phase_u2 = (b2-a2)/u2*360;&lt;br /&gt;
  if(phase_u2 &amp;lt;-360) {phase_u2=phase_u2+360;}&lt;br /&gt;
  &lt;br /&gt;
  phase = phase_u2;&lt;br /&gt;
  //magnitude = max(nsin2)/max(nsin1);&lt;br /&gt;
  //magnitude_pic = abs((fftreal2[b]+fftimag2[b])/(fftreal1[a]+fftimag1[a]));&lt;br /&gt;
  phase_pic = 180+atan2((fftreal2[b]+fftimag2[b]),(fftreal1[a]+fftimag1[a]))*180/PI;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
  &lt;br /&gt;
  //displaying some of the calculation results&lt;br /&gt;
  fill(0);&lt;br /&gt;
  noStroke();&lt;br /&gt;
  rect(width-100,0,100,200);&lt;br /&gt;
  fill(255);&lt;br /&gt;
  text(&amp;quot;abs_mag &amp;quot;+(float)magnitude,width-90,9);&lt;br /&gt;
  text(&amp;quot;abs_phase &amp;quot;+abs_phase,width-90,18);&lt;br /&gt;
  text(&amp;quot;tf_mag &amp;quot;+(int)magnitude_pic,width-90,27);&lt;br /&gt;
  text(&amp;quot;tf_phase &amp;quot;+phase_pic,width-90,36);&lt;br /&gt;
  text(&amp;quot;exp_freq &amp;quot;+(int)freq1,width-90,45);&lt;br /&gt;
  text(&amp;quot;act_freq &amp;quot;+(int)freq2[kk],width-90,54);&lt;br /&gt;
  text(&amp;quot;wave_mag &amp;quot;+(int)(max(nsin2)/max(nsin1)),width-90,63);&lt;br /&gt;
  text(&amp;quot;u2 &amp;quot;+(int)u2,width-90,72);&lt;br /&gt;
  text(&amp;quot;phase_u2 &amp;quot;+(float)phase,width-90,81);&lt;br /&gt;
  text(&amp;quot;a1 &amp;quot;+a1,width-90,90);&lt;br /&gt;
  text(&amp;quot;b1 &amp;quot;+b1,width-90,99);&lt;br /&gt;
  text(&amp;quot;a2 &amp;quot;+(int)a2,width-90,108);&lt;br /&gt;
  text(&amp;quot;b2 &amp;quot;+(int)b2,width-90,117);&lt;br /&gt;
  text(&amp;quot;finish &amp;quot;+finish,width-90,126);&lt;br /&gt;
  &lt;br /&gt;
  //initializing expected frequency values in freq2[]&lt;br /&gt;
  freq2[0] = 100;&lt;br /&gt;
  freq2[1] = 200;&lt;br /&gt;
  freq2[2] = 300;&lt;br /&gt;
  freq2[3] = 400;&lt;br /&gt;
  freq2[4] = 500;&lt;br /&gt;
  freq2[5] = 600;&lt;br /&gt;
  freq2[6] = 700;&lt;br /&gt;
  freq2[7] = 800;&lt;br /&gt;
  freq2[8] = 900;&lt;br /&gt;
  freq2[9] = 1000;&lt;br /&gt;
  freq2[10] = 2000;&lt;br /&gt;
  freq2[11] = 3000;&lt;br /&gt;
  freq2[12] = 4000;&lt;br /&gt;
  freq2[13] = 5000;&lt;br /&gt;
  freq2[14] = 6000;&lt;br /&gt;
  freq2[15] = 7000;&lt;br /&gt;
  freq2[16] = 8000;&lt;br /&gt;
  freq2[17] = 9000;&lt;br /&gt;
  freq2[18] = 10000;&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the magnitude bode plot&lt;br /&gt;
  float bwidth = bx-bx/5;&lt;br /&gt;
  float bheight = by-by/4;&lt;br /&gt;
  float x0 = bx+bx/10;&lt;br /&gt;
  float ya = by/2;&lt;br /&gt;
  float dy = map(20*log(magnitude)/log(10),-100, 100, -1*bheight/2, bheight/2);&lt;br /&gt;
  float dx = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  stroke(0,0,128);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx, ya-dy);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the phase bode plot&lt;br /&gt;
  //float bwidth = bx-bx/5;&lt;br /&gt;
  //float bheight = by-by/4;&lt;br /&gt;
  //float x0 = bx+bx/10;&lt;br /&gt;
  float yb = by*3/2;&lt;br /&gt;
  float dx0 = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  float dy0 = map(phase, -450, 450, -1*bheight/2, bheight/2);&lt;br /&gt;
  stroke(255,0,0);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx0, yb-dy0);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //recording the magnitude and phase bode plot points of the current frequency&lt;br /&gt;
  recmag[kk] = magnitude;&lt;br /&gt;
  recphase[kk] = phase;&lt;br /&gt;
&lt;br /&gt;
  //uncomment to display array values on the right side of the window, &lt;br /&gt;
  //you can change the array variable and how many points in the array you want to see&lt;br /&gt;
  //right now we are displaying the first 128 points of the emitted and sensed sine waves&lt;br /&gt;
  /*        &lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   rect(2*bx,8*k,220,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(sin1[k],2*bx,8*k);&lt;br /&gt;
   text(sin1[k+64],2*bx+50,8*k);&lt;br /&gt;
   text(sin2[k],2*bx+100,8*k);&lt;br /&gt;
   text(sin2[k+64],2*bx+150,8*k);&lt;br /&gt;
 }&lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   //rect(2*bx+150,8*k,10,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(k,2*bx+200,8*k);&lt;br /&gt;
 }&lt;br /&gt;
 */&lt;br /&gt;
 step1 = true; //completed calc()&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
[[Image:team26-dom.GIF | 450px]]  [[Image:team26-dop.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the sensor directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 450px]]  [[Image:team26-middlep.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the sensor is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 450px]]  [[Image:team26-shiftp.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the sensor is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17302</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17302"/>
		<updated>2010-03-17T08:01:00Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Signal Generation Circuit - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS&lt;br /&gt;
*Joshua Peng, BME&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Concept Overview=&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
== Stepper Motor Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:TR JP PP-AD9833 Pic.jpg|right|500px]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Parts&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
Parts&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AD9833 Chip control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
AD9833 requires 16 binary bits for its input. Ad9833_set_freq(int value[]) function will send the array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  And do this job for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of SCLK signal.  Therefor we set the FSYNC pin is low only when we are sending SDATA bits.  Also, we set the SCLK pin to high initially and set it back to low right after we send the SDATA. &amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an ad9833 chip, we need to reset the chip and send a control bits to setup the type of wave. Then, we send lsb and msb of frequency register value, this value will saved in frequency register of the chip and will use it to calculate the actual frequency of the output wave. And then we have to un-reset the chip. This function does all this job for generating sine wave if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHZ. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on ad9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Receiving Waves&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We will read two different sin waves from analog input B4 and B5. &lt;br /&gt;
* B4: Emitter wave&lt;br /&gt;
* B5: Receiver wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitter wave and receiver wave.  The sampling frequency of the timer is determined so it can actually reads 16 points in one cycle of the sin wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100HZ to 10KHZ.  With the PR value equation from lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to PR values we calculated for each sampling frequencies.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each reading frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Reading Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Good references and explanation for FFT calculation can be found in [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// interrupt the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Control Motor&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communicating with processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was receive interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor moves an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop the motor move&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor move forwards until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor move reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerate the speed of motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slow down the speed of motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends all the data to plot graphs in the processing&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to initial position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The codes below is the infinite while loop in main function of our code.&lt;br /&gt;
In order to move the sensor for a half inch 1288 steps are required for stepper motor.  So after 1288 steps, the motor will stop moving and it will start to read data.  After it sends data to processing, the motor start to move again.  For the stepper motor, if we generate the clock with shorter period will make the motor moves faster. So we are controlling the motor speed with Delayms(speed).  If the &amp;#039;speed&amp;#039; incremented, then the motor slows down and if the &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Send to processing&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[http://hades.mech.northwestern.edu/images/3/3c/Main.c Full version of C code]&lt;br /&gt;
&lt;br /&gt;
==Processing Code==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link here and at the end of this section to a zip file with the actual code with comments.  Some of the more important functions are posted.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*int kk = 0; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*int L = 512; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void calc()&lt;br /&gt;
{&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
        &lt;br /&gt;
  //first, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after (on the right side of) &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude,&amp;quot; &amp;quot;abs_phase,&amp;quot; and &amp;quot;phase_pic&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;wave_mag,&amp;quot; &amp;quot;phase&amp;quot; and &amp;quot;phase_u2&amp;quot; are calculated from looking at the sine waves&lt;br /&gt;
  //unfortunately, magnitude_pic wouldn&amp;#039;t work anyway since the &amp;quot;i (or j)&amp;quot; is eliminated, &lt;br /&gt;
  //the imaginary component would just combine with the real component when added in the transfer function. &lt;br /&gt;
  &lt;br /&gt;
  magnitude = max2/max1;&lt;br /&gt;
  abs_phase = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  phase_u2 = (b2-a2)/u2*360;&lt;br /&gt;
  if(phase_u2 &amp;lt;-360) {phase_u2=phase_u2+360;}&lt;br /&gt;
  &lt;br /&gt;
  phase = phase_u2;&lt;br /&gt;
  //magnitude = max(nsin2)/max(nsin1);&lt;br /&gt;
  //magnitude_pic = abs((fftreal2[b]+fftimag2[b])/(fftreal1[a]+fftimag1[a]));&lt;br /&gt;
  phase_pic = 180+atan2((fftreal2[b]+fftimag2[b]),(fftreal1[a]+fftimag1[a]))*180/PI;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
  &lt;br /&gt;
  //displaying some of the calculation results&lt;br /&gt;
  fill(0);&lt;br /&gt;
  noStroke();&lt;br /&gt;
  rect(width-100,0,100,200);&lt;br /&gt;
  fill(255);&lt;br /&gt;
  text(&amp;quot;abs_mag &amp;quot;+(float)magnitude,width-90,9);&lt;br /&gt;
  text(&amp;quot;abs_phase &amp;quot;+abs_phase,width-90,18);&lt;br /&gt;
  text(&amp;quot;tf_mag &amp;quot;+(int)magnitude_pic,width-90,27);&lt;br /&gt;
  text(&amp;quot;tf_phase &amp;quot;+phase_pic,width-90,36);&lt;br /&gt;
  text(&amp;quot;exp_freq &amp;quot;+(int)freq1,width-90,45);&lt;br /&gt;
  text(&amp;quot;act_freq &amp;quot;+(int)freq2[kk],width-90,54);&lt;br /&gt;
  text(&amp;quot;wave_mag &amp;quot;+(int)(max(nsin2)/max(nsin1)),width-90,63);&lt;br /&gt;
  text(&amp;quot;u2 &amp;quot;+(int)u2,width-90,72);&lt;br /&gt;
  text(&amp;quot;phase_u2 &amp;quot;+(float)phase,width-90,81);&lt;br /&gt;
  text(&amp;quot;a1 &amp;quot;+a1,width-90,90);&lt;br /&gt;
  text(&amp;quot;b1 &amp;quot;+b1,width-90,99);&lt;br /&gt;
  text(&amp;quot;a2 &amp;quot;+(int)a2,width-90,108);&lt;br /&gt;
  text(&amp;quot;b2 &amp;quot;+(int)b2,width-90,117);&lt;br /&gt;
  text(&amp;quot;finish &amp;quot;+finish,width-90,126);&lt;br /&gt;
  &lt;br /&gt;
  //initializing expected frequency values in freq2[]&lt;br /&gt;
  freq2[0] = 100;&lt;br /&gt;
  freq2[1] = 200;&lt;br /&gt;
  freq2[2] = 300;&lt;br /&gt;
  freq2[3] = 400;&lt;br /&gt;
  freq2[4] = 500;&lt;br /&gt;
  freq2[5] = 600;&lt;br /&gt;
  freq2[6] = 700;&lt;br /&gt;
  freq2[7] = 800;&lt;br /&gt;
  freq2[8] = 900;&lt;br /&gt;
  freq2[9] = 1000;&lt;br /&gt;
  freq2[10] = 2000;&lt;br /&gt;
  freq2[11] = 3000;&lt;br /&gt;
  freq2[12] = 4000;&lt;br /&gt;
  freq2[13] = 5000;&lt;br /&gt;
  freq2[14] = 6000;&lt;br /&gt;
  freq2[15] = 7000;&lt;br /&gt;
  freq2[16] = 8000;&lt;br /&gt;
  freq2[17] = 9000;&lt;br /&gt;
  freq2[18] = 10000;&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the magnitude bode plot&lt;br /&gt;
  float bwidth = bx-bx/5;&lt;br /&gt;
  float bheight = by-by/4;&lt;br /&gt;
  float x0 = bx+bx/10;&lt;br /&gt;
  float ya = by/2;&lt;br /&gt;
  float dy = map(20*log(magnitude)/log(10),-100, 100, -1*bheight/2, bheight/2);&lt;br /&gt;
  float dx = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  stroke(0,0,128);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx, ya-dy);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the phase bode plot&lt;br /&gt;
  //float bwidth = bx-bx/5;&lt;br /&gt;
  //float bheight = by-by/4;&lt;br /&gt;
  //float x0 = bx+bx/10;&lt;br /&gt;
  float yb = by*3/2;&lt;br /&gt;
  float dx0 = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  float dy0 = map(phase, -450, 450, -1*bheight/2, bheight/2);&lt;br /&gt;
  stroke(255,0,0);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx0, yb-dy0);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //recording the magnitude and phase bode plot points of the current frequency&lt;br /&gt;
  recmag[kk] = magnitude;&lt;br /&gt;
  recphase[kk] = phase;&lt;br /&gt;
&lt;br /&gt;
  //uncomment to display array values on the right side of the window, &lt;br /&gt;
  //you can change the array variable and how many points in the array you want to see&lt;br /&gt;
  //right now we are displaying the first 128 points of the emitted and sensed sine waves&lt;br /&gt;
  /*        &lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   rect(2*bx,8*k,220,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(sin1[k],2*bx,8*k);&lt;br /&gt;
   text(sin1[k+64],2*bx+50,8*k);&lt;br /&gt;
   text(sin2[k],2*bx+100,8*k);&lt;br /&gt;
   text(sin2[k+64],2*bx+150,8*k);&lt;br /&gt;
 }&lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   //rect(2*bx+150,8*k,10,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(k,2*bx+200,8*k);&lt;br /&gt;
 }&lt;br /&gt;
 */&lt;br /&gt;
 step1 = true; //completed calc()&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
[[Image:team26-dom.GIF | 450px]]  [[Image:team26-dop.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the sensor directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 450px]]  [[Image:team26-middlep.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the sensor is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 450px]]  [[Image:team26-shiftp.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the sensor is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17300</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17300"/>
		<updated>2010-03-17T07:58:18Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Signal Generation Circuit - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS&lt;br /&gt;
*Joshua Peng, BME&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Concept Overview=&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
== Stepper Motor Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:TR JP PP-AD9833 Pic.jpg|right|400px]]&lt;br /&gt;
Parts&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
Parts&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AD9833 Chip control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
AD9833 requires 16 binary bits for its input. Ad9833_set_freq(int value[]) function will send the array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  And do this job for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of SCLK signal.  Therefor we set the FSYNC pin is low only when we are sending SDATA bits.  Also, we set the SCLK pin to high initially and set it back to low right after we send the SDATA. &amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an ad9833 chip, we need to reset the chip and send a control bits to setup the type of wave. Then, we send lsb and msb of frequency register value, this value will saved in frequency register of the chip and will use it to calculate the actual frequency of the output wave. And then we have to un-reset the chip. This function does all this job for generating sine wave if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHZ. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on ad9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Receiving Waves&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We will read two different sin waves from analog input B4 and B5. &lt;br /&gt;
* B4: Emitter wave&lt;br /&gt;
* B5: Receiver wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitter wave and receiver wave.  The sampling frequency of the timer is determined so it can actually reads 16 points in one cycle of the sin wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100HZ to 10KHZ.  With the PR value equation from lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to PR values we calculated for each sampling frequencies.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each reading frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Reading Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Good references and explanation for FFT calculation can be found in [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// interrupt the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Control Motor&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communicating with processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was receive interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor moves an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop the motor move&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor move forwards until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor move reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerate the speed of motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slow down the speed of motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends all the data to plot graphs in the processing&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to initial position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The codes below is the infinite while loop in main function of our code.&lt;br /&gt;
In order to move the sensor for a half inch 1288 steps are required for stepper motor.  So after 1288 steps, the motor will stop moving and it will start to read data.  After it sends data to processing, the motor start to move again.  For the stepper motor, if we generate the clock with shorter period will make the motor moves faster. So we are controlling the motor speed with Delayms(speed).  If the &amp;#039;speed&amp;#039; incremented, then the motor slows down and if the &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Send to processing&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[http://hades.mech.northwestern.edu/images/3/3c/Main.c Full version of C code]&lt;br /&gt;
&lt;br /&gt;
==Processing Code==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link here and at the end of this section to a zip file with the actual code with comments.  Some of the more important functions are posted.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*int kk = 0; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*int L = 512; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void calc()&lt;br /&gt;
{&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
        &lt;br /&gt;
  //first, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after (on the right side of) &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude,&amp;quot; &amp;quot;abs_phase,&amp;quot; and &amp;quot;phase_pic&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;wave_mag,&amp;quot; &amp;quot;phase&amp;quot; and &amp;quot;phase_u2&amp;quot; are calculated from looking at the sine waves&lt;br /&gt;
  //unfortunately, magnitude_pic wouldn&amp;#039;t work anyway since the &amp;quot;i (or j)&amp;quot; is eliminated, &lt;br /&gt;
  //the imaginary component would just combine with the real component when added in the transfer function. &lt;br /&gt;
  &lt;br /&gt;
  magnitude = max2/max1;&lt;br /&gt;
  abs_phase = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  phase_u2 = (b2-a2)/u2*360;&lt;br /&gt;
  if(phase_u2 &amp;lt;-360) {phase_u2=phase_u2+360;}&lt;br /&gt;
  &lt;br /&gt;
  phase = phase_u2;&lt;br /&gt;
  //magnitude = max(nsin2)/max(nsin1);&lt;br /&gt;
  //magnitude_pic = abs((fftreal2[b]+fftimag2[b])/(fftreal1[a]+fftimag1[a]));&lt;br /&gt;
  phase_pic = 180+atan2((fftreal2[b]+fftimag2[b]),(fftreal1[a]+fftimag1[a]))*180/PI;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
  &lt;br /&gt;
  //displaying some of the calculation results&lt;br /&gt;
  fill(0);&lt;br /&gt;
  noStroke();&lt;br /&gt;
  rect(width-100,0,100,200);&lt;br /&gt;
  fill(255);&lt;br /&gt;
  text(&amp;quot;abs_mag &amp;quot;+(float)magnitude,width-90,9);&lt;br /&gt;
  text(&amp;quot;abs_phase &amp;quot;+abs_phase,width-90,18);&lt;br /&gt;
  text(&amp;quot;tf_mag &amp;quot;+(int)magnitude_pic,width-90,27);&lt;br /&gt;
  text(&amp;quot;tf_phase &amp;quot;+phase_pic,width-90,36);&lt;br /&gt;
  text(&amp;quot;exp_freq &amp;quot;+(int)freq1,width-90,45);&lt;br /&gt;
  text(&amp;quot;act_freq &amp;quot;+(int)freq2[kk],width-90,54);&lt;br /&gt;
  text(&amp;quot;wave_mag &amp;quot;+(int)(max(nsin2)/max(nsin1)),width-90,63);&lt;br /&gt;
  text(&amp;quot;u2 &amp;quot;+(int)u2,width-90,72);&lt;br /&gt;
  text(&amp;quot;phase_u2 &amp;quot;+(float)phase,width-90,81);&lt;br /&gt;
  text(&amp;quot;a1 &amp;quot;+a1,width-90,90);&lt;br /&gt;
  text(&amp;quot;b1 &amp;quot;+b1,width-90,99);&lt;br /&gt;
  text(&amp;quot;a2 &amp;quot;+(int)a2,width-90,108);&lt;br /&gt;
  text(&amp;quot;b2 &amp;quot;+(int)b2,width-90,117);&lt;br /&gt;
  text(&amp;quot;finish &amp;quot;+finish,width-90,126);&lt;br /&gt;
  &lt;br /&gt;
  //initializing expected frequency values in freq2[]&lt;br /&gt;
  freq2[0] = 100;&lt;br /&gt;
  freq2[1] = 200;&lt;br /&gt;
  freq2[2] = 300;&lt;br /&gt;
  freq2[3] = 400;&lt;br /&gt;
  freq2[4] = 500;&lt;br /&gt;
  freq2[5] = 600;&lt;br /&gt;
  freq2[6] = 700;&lt;br /&gt;
  freq2[7] = 800;&lt;br /&gt;
  freq2[8] = 900;&lt;br /&gt;
  freq2[9] = 1000;&lt;br /&gt;
  freq2[10] = 2000;&lt;br /&gt;
  freq2[11] = 3000;&lt;br /&gt;
  freq2[12] = 4000;&lt;br /&gt;
  freq2[13] = 5000;&lt;br /&gt;
  freq2[14] = 6000;&lt;br /&gt;
  freq2[15] = 7000;&lt;br /&gt;
  freq2[16] = 8000;&lt;br /&gt;
  freq2[17] = 9000;&lt;br /&gt;
  freq2[18] = 10000;&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the magnitude bode plot&lt;br /&gt;
  float bwidth = bx-bx/5;&lt;br /&gt;
  float bheight = by-by/4;&lt;br /&gt;
  float x0 = bx+bx/10;&lt;br /&gt;
  float ya = by/2;&lt;br /&gt;
  float dy = map(20*log(magnitude)/log(10),-100, 100, -1*bheight/2, bheight/2);&lt;br /&gt;
  float dx = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  stroke(0,0,128);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx, ya-dy);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the phase bode plot&lt;br /&gt;
  //float bwidth = bx-bx/5;&lt;br /&gt;
  //float bheight = by-by/4;&lt;br /&gt;
  //float x0 = bx+bx/10;&lt;br /&gt;
  float yb = by*3/2;&lt;br /&gt;
  float dx0 = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  float dy0 = map(phase, -450, 450, -1*bheight/2, bheight/2);&lt;br /&gt;
  stroke(255,0,0);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx0, yb-dy0);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //recording the magnitude and phase bode plot points of the current frequency&lt;br /&gt;
  recmag[kk] = magnitude;&lt;br /&gt;
  recphase[kk] = phase;&lt;br /&gt;
&lt;br /&gt;
  //uncomment to display array values on the right side of the window, &lt;br /&gt;
  //you can change the array variable and how many points in the array you want to see&lt;br /&gt;
  //right now we are displaying the first 128 points of the emitted and sensed sine waves&lt;br /&gt;
  /*        &lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   rect(2*bx,8*k,220,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(sin1[k],2*bx,8*k);&lt;br /&gt;
   text(sin1[k+64],2*bx+50,8*k);&lt;br /&gt;
   text(sin2[k],2*bx+100,8*k);&lt;br /&gt;
   text(sin2[k+64],2*bx+150,8*k);&lt;br /&gt;
 }&lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   //rect(2*bx+150,8*k,10,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(k,2*bx+200,8*k);&lt;br /&gt;
 }&lt;br /&gt;
 */&lt;br /&gt;
 step1 = true; //completed calc()&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
[[Image:team26-dom.GIF | 450px]]  [[Image:team26-dop.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the sensor directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 450px]]  [[Image:team26-middlep.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the sensor is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 450px]]  [[Image:team26-shiftp.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the sensor is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17298</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17298"/>
		<updated>2010-03-17T07:57:17Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Signal Generation Circuit - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS&lt;br /&gt;
*Joshua Peng, BME&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Concept Overview=&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
== Stepper Motor Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The AD9833 is a surface mount function generating chip that allows us to emit analog signals at discrete frequencies under control from the PIC. Because the the signal out of the chip is between 0 and 900 mV an amplifier is used to boost the signal by a factor of 2.2.&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[image:TR JP PP-AD9833 Pic.jpg|right|400px]]&lt;br /&gt;
Parts&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**1x AD9833&lt;br /&gt;
***Surface Mount Chip&lt;br /&gt;
***Custom PCB&lt;br /&gt;
**1x Op amp(LM741)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x.01uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K&lt;br /&gt;
**1x 2.2K&lt;br /&gt;
* Miscellaneous&lt;br /&gt;
**20 MHz Clock&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
Parts&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AD9833 Chip control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
AD9833 requires 16 binary bits for its input. Ad9833_set_freq(int value[]) function will send the array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  And do this job for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of SCLK signal.  Therefor we set the FSYNC pin is low only when we are sending SDATA bits.  Also, we set the SCLK pin to high initially and set it back to low right after we send the SDATA. &amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an ad9833 chip, we need to reset the chip and send a control bits to setup the type of wave. Then, we send lsb and msb of frequency register value, this value will saved in frequency register of the chip and will use it to calculate the actual frequency of the output wave. And then we have to un-reset the chip. This function does all this job for generating sine wave if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHZ. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on ad9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Receiving Waves&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We will read two different sin waves from analog input B4 and B5. &lt;br /&gt;
* B4: Emitter wave&lt;br /&gt;
* B5: Receiver wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitter wave and receiver wave.  The sampling frequency of the timer is determined so it can actually reads 16 points in one cycle of the sin wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100HZ to 10KHZ.  With the PR value equation from lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to PR values we calculated for each sampling frequencies.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each reading frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Reading Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Good references and explanation for FFT calculation can be found in [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// interrupt the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Control Motor&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communicating with processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was receive interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor moves an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop the motor move&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor move forwards until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor move reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerate the speed of motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slow down the speed of motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends all the data to plot graphs in the processing&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to initial position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The codes below is the infinite while loop in main function of our code.&lt;br /&gt;
In order to move the sensor for a half inch 1288 steps are required for stepper motor.  So after 1288 steps, the motor will stop moving and it will start to read data.  After it sends data to processing, the motor start to move again.  For the stepper motor, if we generate the clock with shorter period will make the motor moves faster. So we are controlling the motor speed with Delayms(speed).  If the &amp;#039;speed&amp;#039; incremented, then the motor slows down and if the &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Send to processing&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[http://hades.mech.northwestern.edu/images/3/3c/Main.c Full version of C code]&lt;br /&gt;
&lt;br /&gt;
==Processing Code==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link here and at the end of this section to a zip file with the actual code with comments.  Some of the more important functions are posted.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*int kk = 0; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*int L = 512; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void calc()&lt;br /&gt;
{&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
        &lt;br /&gt;
  //first, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after (on the right side of) &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude,&amp;quot; &amp;quot;abs_phase,&amp;quot; and &amp;quot;phase_pic&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;wave_mag,&amp;quot; &amp;quot;phase&amp;quot; and &amp;quot;phase_u2&amp;quot; are calculated from looking at the sine waves&lt;br /&gt;
  //unfortunately, magnitude_pic wouldn&amp;#039;t work anyway since the &amp;quot;i (or j)&amp;quot; is eliminated, &lt;br /&gt;
  //the imaginary component would just combine with the real component when added in the transfer function. &lt;br /&gt;
  &lt;br /&gt;
  magnitude = max2/max1;&lt;br /&gt;
  abs_phase = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  phase_u2 = (b2-a2)/u2*360;&lt;br /&gt;
  if(phase_u2 &amp;lt;-360) {phase_u2=phase_u2+360;}&lt;br /&gt;
  &lt;br /&gt;
  phase = phase_u2;&lt;br /&gt;
  //magnitude = max(nsin2)/max(nsin1);&lt;br /&gt;
  //magnitude_pic = abs((fftreal2[b]+fftimag2[b])/(fftreal1[a]+fftimag1[a]));&lt;br /&gt;
  phase_pic = 180+atan2((fftreal2[b]+fftimag2[b]),(fftreal1[a]+fftimag1[a]))*180/PI;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
  &lt;br /&gt;
  //displaying some of the calculation results&lt;br /&gt;
  fill(0);&lt;br /&gt;
  noStroke();&lt;br /&gt;
  rect(width-100,0,100,200);&lt;br /&gt;
  fill(255);&lt;br /&gt;
  text(&amp;quot;abs_mag &amp;quot;+(float)magnitude,width-90,9);&lt;br /&gt;
  text(&amp;quot;abs_phase &amp;quot;+abs_phase,width-90,18);&lt;br /&gt;
  text(&amp;quot;tf_mag &amp;quot;+(int)magnitude_pic,width-90,27);&lt;br /&gt;
  text(&amp;quot;tf_phase &amp;quot;+phase_pic,width-90,36);&lt;br /&gt;
  text(&amp;quot;exp_freq &amp;quot;+(int)freq1,width-90,45);&lt;br /&gt;
  text(&amp;quot;act_freq &amp;quot;+(int)freq2[kk],width-90,54);&lt;br /&gt;
  text(&amp;quot;wave_mag &amp;quot;+(int)(max(nsin2)/max(nsin1)),width-90,63);&lt;br /&gt;
  text(&amp;quot;u2 &amp;quot;+(int)u2,width-90,72);&lt;br /&gt;
  text(&amp;quot;phase_u2 &amp;quot;+(float)phase,width-90,81);&lt;br /&gt;
  text(&amp;quot;a1 &amp;quot;+a1,width-90,90);&lt;br /&gt;
  text(&amp;quot;b1 &amp;quot;+b1,width-90,99);&lt;br /&gt;
  text(&amp;quot;a2 &amp;quot;+(int)a2,width-90,108);&lt;br /&gt;
  text(&amp;quot;b2 &amp;quot;+(int)b2,width-90,117);&lt;br /&gt;
  text(&amp;quot;finish &amp;quot;+finish,width-90,126);&lt;br /&gt;
  &lt;br /&gt;
  //initializing expected frequency values in freq2[]&lt;br /&gt;
  freq2[0] = 100;&lt;br /&gt;
  freq2[1] = 200;&lt;br /&gt;
  freq2[2] = 300;&lt;br /&gt;
  freq2[3] = 400;&lt;br /&gt;
  freq2[4] = 500;&lt;br /&gt;
  freq2[5] = 600;&lt;br /&gt;
  freq2[6] = 700;&lt;br /&gt;
  freq2[7] = 800;&lt;br /&gt;
  freq2[8] = 900;&lt;br /&gt;
  freq2[9] = 1000;&lt;br /&gt;
  freq2[10] = 2000;&lt;br /&gt;
  freq2[11] = 3000;&lt;br /&gt;
  freq2[12] = 4000;&lt;br /&gt;
  freq2[13] = 5000;&lt;br /&gt;
  freq2[14] = 6000;&lt;br /&gt;
  freq2[15] = 7000;&lt;br /&gt;
  freq2[16] = 8000;&lt;br /&gt;
  freq2[17] = 9000;&lt;br /&gt;
  freq2[18] = 10000;&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the magnitude bode plot&lt;br /&gt;
  float bwidth = bx-bx/5;&lt;br /&gt;
  float bheight = by-by/4;&lt;br /&gt;
  float x0 = bx+bx/10;&lt;br /&gt;
  float ya = by/2;&lt;br /&gt;
  float dy = map(20*log(magnitude)/log(10),-100, 100, -1*bheight/2, bheight/2);&lt;br /&gt;
  float dx = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  stroke(0,0,128);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx, ya-dy);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the phase bode plot&lt;br /&gt;
  //float bwidth = bx-bx/5;&lt;br /&gt;
  //float bheight = by-by/4;&lt;br /&gt;
  //float x0 = bx+bx/10;&lt;br /&gt;
  float yb = by*3/2;&lt;br /&gt;
  float dx0 = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  float dy0 = map(phase, -450, 450, -1*bheight/2, bheight/2);&lt;br /&gt;
  stroke(255,0,0);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx0, yb-dy0);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //recording the magnitude and phase bode plot points of the current frequency&lt;br /&gt;
  recmag[kk] = magnitude;&lt;br /&gt;
  recphase[kk] = phase;&lt;br /&gt;
&lt;br /&gt;
  //uncomment to display array values on the right side of the window, &lt;br /&gt;
  //you can change the array variable and how many points in the array you want to see&lt;br /&gt;
  //right now we are displaying the first 128 points of the emitted and sensed sine waves&lt;br /&gt;
  /*        &lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   rect(2*bx,8*k,220,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(sin1[k],2*bx,8*k);&lt;br /&gt;
   text(sin1[k+64],2*bx+50,8*k);&lt;br /&gt;
   text(sin2[k],2*bx+100,8*k);&lt;br /&gt;
   text(sin2[k+64],2*bx+150,8*k);&lt;br /&gt;
 }&lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   //rect(2*bx+150,8*k,10,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(k,2*bx+200,8*k);&lt;br /&gt;
 }&lt;br /&gt;
 */&lt;br /&gt;
 step1 = true; //completed calc()&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
[[Image:team26-dom.GIF | 450px]]  [[Image:team26-dop.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the sensor directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 450px]]  [[Image:team26-middlep.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the sensor is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 450px]]  [[Image:team26-shiftp.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the sensor is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-AD9833_Pic.jpg&amp;diff=17296</id>
		<title>File:TR JP PP-AD9833 Pic.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-AD9833_Pic.jpg&amp;diff=17296"/>
		<updated>2010-03-17T07:55:12Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-AD9833_circuit.jpg&amp;diff=17294</id>
		<title>File:TR JP PP-AD9833 circuit.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-AD9833_circuit.jpg&amp;diff=17294"/>
		<updated>2010-03-17T07:50:03Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: uploaded a new version of &amp;quot;Image:TR JP PP-AD9833 circuit.jpg&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17288</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17288"/>
		<updated>2010-03-17T07:32:20Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Signal Amplification/Level Shifting Circuit - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS&lt;br /&gt;
*Joshua Peng, BME&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Concept Overview=&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
== Stepper Motor Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The sensed wave is generated by reading in the two waves at the sensor electrodes and comparing their signals. &lt;br /&gt;
*Each signal is initially buffered using a voltage follower&lt;br /&gt;
*Two signals are run though balancing circuitry to allow for a &amp;quot;zeroing&amp;quot; of the sensor&lt;br /&gt;
*Two signals serve as inputs to Instrumentation amp which has a fixed gain of 1000&lt;br /&gt;
*Output signal is run through a bandpass filter&lt;br /&gt;
*Final signal is level shifted so that it can be read into the PIC&amp;#039;s ADC which requires the signal be between 0 an 3.3 volts.&lt;br /&gt;
&lt;br /&gt;
Note that this circuit is built in solder due to the extremely small voltage changes that need to be detected between the two sensed waves by the instrumentation amp. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-Amplifier_Pic.jpg| 500px|right]]&lt;br /&gt;
Parts&lt;br /&gt;
*IC&amp;#039;s&lt;br /&gt;
**3x Op Amps(LM741)&lt;br /&gt;
**1x Inst Amp(INA129)&lt;br /&gt;
*Capacitors&lt;br /&gt;
**2x .1uF&lt;br /&gt;
**1x 1uF&lt;br /&gt;
**1x .02uF&lt;br /&gt;
*Resistors&lt;br /&gt;
**1x 1K Potentiometer&lt;br /&gt;
**2x 47K&lt;br /&gt;
**2x 5K&lt;br /&gt;
**1x 2K&lt;br /&gt;
**1x 3K&lt;br /&gt;
**2x 1K&lt;br /&gt;
**1x 6.4K&lt;br /&gt;
**1x 3.3K&lt;br /&gt;
*Miscellaneous&lt;br /&gt;
**50 Pin Header&lt;br /&gt;
**Solder Board&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AD9833 Chip control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
AD9833 requires 16 binary bits for its input. Ad9833_set_freq(int value[]) function will send the array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  And do this job for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of SCLK signal.  Therefor we set the FSYNC pin is low only when we are sending SDATA bits.  Also, we set the SCLK pin to high initially and set it back to low right after we send the SDATA. &amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an ad9833 chip, we need to reset the chip and send a control bits to setup the type of wave. Then, we send lsb and msb of frequency register value, this value will saved in frequency register of the chip and will use it to calculate the actual frequency of the output wave. And then we have to un-reset the chip. This function does all this job for generating sine wave if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHZ. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on ad9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Receiving Waves&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We will read two different sin waves from analog input B4 and B5. &lt;br /&gt;
* B4: Emitter wave&lt;br /&gt;
* B5: Receiver wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitter wave and receiver wave.  The sampling frequency of the timer is determined so it can actually reads 16 points in one cycle of the sin wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100HZ to 10KHZ.  With the PR value equation from lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to PR values we calculated for each sampling frequencies.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each reading frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Reading Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Good references and explanation for FFT calculation can be found in [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// interrupt the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Control Motor&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communicating with processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was receive interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor moves an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop the motor move&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor move forwards until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor move reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerate the speed of motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slow down the speed of motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends all the data to plot graphs in the processing&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to initial position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The codes below is the infinite while loop in main function of our code.&lt;br /&gt;
In order to move the sensor for a half inch 1288 steps are required for stepper motor.  So after 1288 steps, the motor will stop moving and it will start to read data.  After it sends data to processing, the motor start to move again.  For the stepper motor, if we generate the clock with shorter period will make the motor moves faster. So we are controlling the motor speed with Delayms(speed).  If the &amp;#039;speed&amp;#039; incremented, then the motor slows down and if the &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Send to processing&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[http://hades.mech.northwestern.edu/images/3/3c/Main.c Full version of C code]&lt;br /&gt;
&lt;br /&gt;
==Processing Code==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link here and at the end of this section to a zip file with the actual code with comments.  Some of the more important functions are posted.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*int kk = 0; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*int L = 512; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void calc()&lt;br /&gt;
{&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
        &lt;br /&gt;
  //first, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after (on the right side of) &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude,&amp;quot; &amp;quot;abs_phase,&amp;quot; and &amp;quot;phase_pic&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;wave_mag,&amp;quot; &amp;quot;phase&amp;quot; and &amp;quot;phase_u2&amp;quot; are calculated from looking at the sine waves&lt;br /&gt;
  //unfortunately, magnitude_pic wouldn&amp;#039;t work anyway since the &amp;quot;i (or j)&amp;quot; is eliminated, &lt;br /&gt;
  //the imaginary component would just combine with the real component when added in the transfer function. &lt;br /&gt;
  &lt;br /&gt;
  magnitude = max2/max1;&lt;br /&gt;
  abs_phase = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  phase_u2 = (b2-a2)/u2*360;&lt;br /&gt;
  if(phase_u2 &amp;lt;-360) {phase_u2=phase_u2+360;}&lt;br /&gt;
  &lt;br /&gt;
  phase = phase_u2;&lt;br /&gt;
  //magnitude = max(nsin2)/max(nsin1);&lt;br /&gt;
  //magnitude_pic = abs((fftreal2[b]+fftimag2[b])/(fftreal1[a]+fftimag1[a]));&lt;br /&gt;
  phase_pic = 180+atan2((fftreal2[b]+fftimag2[b]),(fftreal1[a]+fftimag1[a]))*180/PI;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
  &lt;br /&gt;
  //displaying some of the calculation results&lt;br /&gt;
  fill(0);&lt;br /&gt;
  noStroke();&lt;br /&gt;
  rect(width-100,0,100,200);&lt;br /&gt;
  fill(255);&lt;br /&gt;
  text(&amp;quot;abs_mag &amp;quot;+(float)magnitude,width-90,9);&lt;br /&gt;
  text(&amp;quot;abs_phase &amp;quot;+abs_phase,width-90,18);&lt;br /&gt;
  text(&amp;quot;tf_mag &amp;quot;+(int)magnitude_pic,width-90,27);&lt;br /&gt;
  text(&amp;quot;tf_phase &amp;quot;+phase_pic,width-90,36);&lt;br /&gt;
  text(&amp;quot;exp_freq &amp;quot;+(int)freq1,width-90,45);&lt;br /&gt;
  text(&amp;quot;act_freq &amp;quot;+(int)freq2[kk],width-90,54);&lt;br /&gt;
  text(&amp;quot;wave_mag &amp;quot;+(int)(max(nsin2)/max(nsin1)),width-90,63);&lt;br /&gt;
  text(&amp;quot;u2 &amp;quot;+(int)u2,width-90,72);&lt;br /&gt;
  text(&amp;quot;phase_u2 &amp;quot;+(float)phase,width-90,81);&lt;br /&gt;
  text(&amp;quot;a1 &amp;quot;+a1,width-90,90);&lt;br /&gt;
  text(&amp;quot;b1 &amp;quot;+b1,width-90,99);&lt;br /&gt;
  text(&amp;quot;a2 &amp;quot;+(int)a2,width-90,108);&lt;br /&gt;
  text(&amp;quot;b2 &amp;quot;+(int)b2,width-90,117);&lt;br /&gt;
  text(&amp;quot;finish &amp;quot;+finish,width-90,126);&lt;br /&gt;
  &lt;br /&gt;
  //initializing expected frequency values in freq2[]&lt;br /&gt;
  freq2[0] = 100;&lt;br /&gt;
  freq2[1] = 200;&lt;br /&gt;
  freq2[2] = 300;&lt;br /&gt;
  freq2[3] = 400;&lt;br /&gt;
  freq2[4] = 500;&lt;br /&gt;
  freq2[5] = 600;&lt;br /&gt;
  freq2[6] = 700;&lt;br /&gt;
  freq2[7] = 800;&lt;br /&gt;
  freq2[8] = 900;&lt;br /&gt;
  freq2[9] = 1000;&lt;br /&gt;
  freq2[10] = 2000;&lt;br /&gt;
  freq2[11] = 3000;&lt;br /&gt;
  freq2[12] = 4000;&lt;br /&gt;
  freq2[13] = 5000;&lt;br /&gt;
  freq2[14] = 6000;&lt;br /&gt;
  freq2[15] = 7000;&lt;br /&gt;
  freq2[16] = 8000;&lt;br /&gt;
  freq2[17] = 9000;&lt;br /&gt;
  freq2[18] = 10000;&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the magnitude bode plot&lt;br /&gt;
  float bwidth = bx-bx/5;&lt;br /&gt;
  float bheight = by-by/4;&lt;br /&gt;
  float x0 = bx+bx/10;&lt;br /&gt;
  float ya = by/2;&lt;br /&gt;
  float dy = map(20*log(magnitude)/log(10),-100, 100, -1*bheight/2, bheight/2);&lt;br /&gt;
  float dx = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  stroke(0,0,128);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx, ya-dy);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the phase bode plot&lt;br /&gt;
  //float bwidth = bx-bx/5;&lt;br /&gt;
  //float bheight = by-by/4;&lt;br /&gt;
  //float x0 = bx+bx/10;&lt;br /&gt;
  float yb = by*3/2;&lt;br /&gt;
  float dx0 = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  float dy0 = map(phase, -450, 450, -1*bheight/2, bheight/2);&lt;br /&gt;
  stroke(255,0,0);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx0, yb-dy0);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //recording the magnitude and phase bode plot points of the current frequency&lt;br /&gt;
  recmag[kk] = magnitude;&lt;br /&gt;
  recphase[kk] = phase;&lt;br /&gt;
&lt;br /&gt;
  //uncomment to display array values on the right side of the window, &lt;br /&gt;
  //you can change the array variable and how many points in the array you want to see&lt;br /&gt;
  //right now we are displaying the first 128 points of the emitted and sensed sine waves&lt;br /&gt;
  /*        &lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   rect(2*bx,8*k,220,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(sin1[k],2*bx,8*k);&lt;br /&gt;
   text(sin1[k+64],2*bx+50,8*k);&lt;br /&gt;
   text(sin2[k],2*bx+100,8*k);&lt;br /&gt;
   text(sin2[k+64],2*bx+150,8*k);&lt;br /&gt;
 }&lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   //rect(2*bx+150,8*k,10,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(k,2*bx+200,8*k);&lt;br /&gt;
 }&lt;br /&gt;
 */&lt;br /&gt;
 step1 = true; //completed calc()&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
[[Image:team26-dom.GIF | 450px]]  [[Image:team26-dop.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the sensor directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 450px]]  [[Image:team26-middlep.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the sensor is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 450px]]  [[Image:team26-shiftp.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the sensor is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-Amplifier_Pic.jpg&amp;diff=17283</id>
		<title>File:TR JP PP-Amplifier Pic.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-Amplifier_Pic.jpg&amp;diff=17283"/>
		<updated>2010-03-17T07:24:47Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: uploaded a new version of &amp;quot;Image:TR JP PP-Amplifier Pic.jpg&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-Amplifier_Pic.jpg&amp;diff=17282</id>
		<title>File:TR JP PP-Amplifier Pic.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-Amplifier_Pic.jpg&amp;diff=17282"/>
		<updated>2010-03-17T07:23:17Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17279</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17279"/>
		<updated>2010-03-17T07:05:03Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Signal Amplification/Level Shifting Circuit - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS&lt;br /&gt;
*Joshua Peng, BME&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Concept Overview=&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
== Stepper Motor Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit - Electrical Design==&lt;br /&gt;
[[image:TR_JP_PP-Amplification_Circuit.png]]&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AD9833 Chip control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
AD9833 requires 16 binary bits for its input. Ad9833_set_freq(int value[]) function will send the array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  And do this job for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of SCLK signal.  Therefor we set the FSYNC pin is low only when we are sending SDATA bits.  Also, we set the SCLK pin to high initially and set it back to low right after we send the SDATA. &amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an ad9833 chip, we need to reset the chip and send a control bits to setup the type of wave. Then, we send lsb and msb of frequency register value, this value will saved in frequency register of the chip and will use it to calculate the actual frequency of the output wave. And then we have to un-reset the chip. This function does all this job for generating sine wave if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHZ. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on ad9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Receiving Waves&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We will read two different sin waves from analog input B4 and B5. &lt;br /&gt;
* B4: Emitter wave&lt;br /&gt;
* B5: Receiver wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitter wave and receiver wave.  The sampling frequency of the timer is determined so it can actually reads 16 points in one cycle of the sin wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100HZ to 10KHZ.  With the PR value equation from lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to PR values we calculated for each sampling frequencies.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each reading frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Reading Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Good references and explanation for FFT calculation can be found in [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// interrupt the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Control Motor&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communicating with processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was receive interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor moves an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop the motor move&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor move forwards until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor move reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerate the speed of motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slow down the speed of motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends all the data to plot graphs in the processing&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to initial position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The codes below is the infinite while loop in main function of our code.&lt;br /&gt;
In order to move the sensor for a half inch 1288 steps are required for stepper motor.  So after 1288 steps, the motor will stop moving and it will start to read data.  After it sends data to processing, the motor start to move again.  For the stepper motor, if we generate the clock with shorter period will make the motor moves faster. So we are controlling the motor speed with Delayms(speed).  If the &amp;#039;speed&amp;#039; incremented, then the motor slows down and if the &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Send to processing&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[http://hades.mech.northwestern.edu/images/3/3c/Main.c Full version of C code]&lt;br /&gt;
&lt;br /&gt;
==Processing Code==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link here and at the end of this section to a zip file with the actual code with comments.  Some of the more important functions are posted.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*int kk = 0; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*int L = 512; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void calc()&lt;br /&gt;
{&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
        &lt;br /&gt;
  //first, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after (on the right side of) &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude,&amp;quot; &amp;quot;abs_phase,&amp;quot; and &amp;quot;phase_pic&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;wave_mag,&amp;quot; &amp;quot;phase&amp;quot; and &amp;quot;phase_u2&amp;quot; are calculated from looking at the sine waves&lt;br /&gt;
  //unfortunately, magnitude_pic wouldn&amp;#039;t work anyway since the &amp;quot;i (or j)&amp;quot; is eliminated, &lt;br /&gt;
  //the imaginary component would just combine with the real component when added in the transfer function. &lt;br /&gt;
  &lt;br /&gt;
  magnitude = max2/max1;&lt;br /&gt;
  abs_phase = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  phase_u2 = (b2-a2)/u2*360;&lt;br /&gt;
  if(phase_u2 &amp;lt;-360) {phase_u2=phase_u2+360;}&lt;br /&gt;
  &lt;br /&gt;
  phase = phase_u2;&lt;br /&gt;
  //magnitude = max(nsin2)/max(nsin1);&lt;br /&gt;
  //magnitude_pic = abs((fftreal2[b]+fftimag2[b])/(fftreal1[a]+fftimag1[a]));&lt;br /&gt;
  phase_pic = 180+atan2((fftreal2[b]+fftimag2[b]),(fftreal1[a]+fftimag1[a]))*180/PI;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
  &lt;br /&gt;
  //displaying some of the calculation results&lt;br /&gt;
  fill(0);&lt;br /&gt;
  noStroke();&lt;br /&gt;
  rect(width-100,0,100,200);&lt;br /&gt;
  fill(255);&lt;br /&gt;
  text(&amp;quot;abs_mag &amp;quot;+(float)magnitude,width-90,9);&lt;br /&gt;
  text(&amp;quot;abs_phase &amp;quot;+abs_phase,width-90,18);&lt;br /&gt;
  text(&amp;quot;tf_mag &amp;quot;+(int)magnitude_pic,width-90,27);&lt;br /&gt;
  text(&amp;quot;tf_phase &amp;quot;+phase_pic,width-90,36);&lt;br /&gt;
  text(&amp;quot;exp_freq &amp;quot;+(int)freq1,width-90,45);&lt;br /&gt;
  text(&amp;quot;act_freq &amp;quot;+(int)freq2[kk],width-90,54);&lt;br /&gt;
  text(&amp;quot;wave_mag &amp;quot;+(int)(max(nsin2)/max(nsin1)),width-90,63);&lt;br /&gt;
  text(&amp;quot;u2 &amp;quot;+(int)u2,width-90,72);&lt;br /&gt;
  text(&amp;quot;phase_u2 &amp;quot;+(float)phase,width-90,81);&lt;br /&gt;
  text(&amp;quot;a1 &amp;quot;+a1,width-90,90);&lt;br /&gt;
  text(&amp;quot;b1 &amp;quot;+b1,width-90,99);&lt;br /&gt;
  text(&amp;quot;a2 &amp;quot;+(int)a2,width-90,108);&lt;br /&gt;
  text(&amp;quot;b2 &amp;quot;+(int)b2,width-90,117);&lt;br /&gt;
  text(&amp;quot;finish &amp;quot;+finish,width-90,126);&lt;br /&gt;
  &lt;br /&gt;
  //initializing expected frequency values in freq2[]&lt;br /&gt;
  freq2[0] = 100;&lt;br /&gt;
  freq2[1] = 200;&lt;br /&gt;
  freq2[2] = 300;&lt;br /&gt;
  freq2[3] = 400;&lt;br /&gt;
  freq2[4] = 500;&lt;br /&gt;
  freq2[5] = 600;&lt;br /&gt;
  freq2[6] = 700;&lt;br /&gt;
  freq2[7] = 800;&lt;br /&gt;
  freq2[8] = 900;&lt;br /&gt;
  freq2[9] = 1000;&lt;br /&gt;
  freq2[10] = 2000;&lt;br /&gt;
  freq2[11] = 3000;&lt;br /&gt;
  freq2[12] = 4000;&lt;br /&gt;
  freq2[13] = 5000;&lt;br /&gt;
  freq2[14] = 6000;&lt;br /&gt;
  freq2[15] = 7000;&lt;br /&gt;
  freq2[16] = 8000;&lt;br /&gt;
  freq2[17] = 9000;&lt;br /&gt;
  freq2[18] = 10000;&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the magnitude bode plot&lt;br /&gt;
  float bwidth = bx-bx/5;&lt;br /&gt;
  float bheight = by-by/4;&lt;br /&gt;
  float x0 = bx+bx/10;&lt;br /&gt;
  float ya = by/2;&lt;br /&gt;
  float dy = map(20*log(magnitude)/log(10),-100, 100, -1*bheight/2, bheight/2);&lt;br /&gt;
  float dx = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  stroke(0,0,128);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx, ya-dy);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the phase bode plot&lt;br /&gt;
  //float bwidth = bx-bx/5;&lt;br /&gt;
  //float bheight = by-by/4;&lt;br /&gt;
  //float x0 = bx+bx/10;&lt;br /&gt;
  float yb = by*3/2;&lt;br /&gt;
  float dx0 = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  float dy0 = map(phase, -450, 450, -1*bheight/2, bheight/2);&lt;br /&gt;
  stroke(255,0,0);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx0, yb-dy0);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //recording the magnitude and phase bode plot points of the current frequency&lt;br /&gt;
  recmag[kk] = magnitude;&lt;br /&gt;
  recphase[kk] = phase;&lt;br /&gt;
&lt;br /&gt;
  //uncomment to display array values on the right side of the window, &lt;br /&gt;
  //you can change the array variable and how many points in the array you want to see&lt;br /&gt;
  //right now we are displaying the first 128 points of the emitted and sensed sine waves&lt;br /&gt;
  /*        &lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   rect(2*bx,8*k,220,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(sin1[k],2*bx,8*k);&lt;br /&gt;
   text(sin1[k+64],2*bx+50,8*k);&lt;br /&gt;
   text(sin2[k],2*bx+100,8*k);&lt;br /&gt;
   text(sin2[k+64],2*bx+150,8*k);&lt;br /&gt;
 }&lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   //rect(2*bx+150,8*k,10,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(k,2*bx+200,8*k);&lt;br /&gt;
 }&lt;br /&gt;
 */&lt;br /&gt;
 step1 = true; //completed calc()&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
[[Image:team26-dom.GIF | 450px]]  [[Image:team26-dop.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the sensor directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 450px]]  [[Image:team26-middlep.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the sensor is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 450px]]  [[Image:team26-shiftp.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the sensor is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-Amplification_Circuit.png&amp;diff=17277</id>
		<title>File:TR JP PP-Amplification Circuit.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-Amplification_Circuit.png&amp;diff=17277"/>
		<updated>2010-03-17T07:04:35Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17275</id>
		<title>Variable Frequency Electrosense</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Variable_Frequency_Electrosense&amp;diff=17275"/>
		<updated>2010-03-17T07:02:41Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: /* Signal Generation Circuit - Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&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;
==Team==&lt;br /&gt;
*Tod Reynolds, EECS 2010&lt;br /&gt;
*Pill Gun Park, EECS&lt;br /&gt;
*Joshua Peng, BME&lt;br /&gt;
[[image:Team26-Group Pic.jpg]]&lt;br /&gt;
&lt;br /&gt;
=Concept Overview=&lt;br /&gt;
&lt;br /&gt;
=Mechanical Design=&lt;br /&gt;
&lt;br /&gt;
==Electrosense Water Tank - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
==Linear Actuator - Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
=Electrical Design=&lt;br /&gt;
&lt;br /&gt;
== Stepper Motor Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-stepper_circuit.png]]&lt;br /&gt;
&lt;br /&gt;
==Signal Generation Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[image: TR_JP_PP-AD9833_circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Signal Amplification/Level Shifting Circuit - Electrical Design==&lt;br /&gt;
&lt;br /&gt;
=Code=&lt;br /&gt;
&lt;br /&gt;
==PIC Code==&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;AD9833 Chip control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
AD9833 requires 16 binary bits for its input. Ad9833_set_freq(int value[]) function will send the array of binary numbers to the AD9833 chip.  In this function, if the binary number is 0, we set the SDATA pin to low and if the binary number is 1, we set the SDATA pin to high.  And do this job for all 16 bits.  According to the datasheet for AD9833, see [http://www.analog.com/static/imported-files/Data_Sheets/AD9833.pdf here], the chip reads the data when FSYNC is low and at the low edge of SCLK signal.  Therefor we set the FSYNC pin is low only when we are sending SDATA bits.  Also, we set the SCLK pin to high initially and set it back to low right after we send the SDATA. &amp;lt;pre&amp;gt;&lt;br /&gt;
#define PIN_A2			LATAbits.LATA2  //FSYNC&lt;br /&gt;
#define PIN_A3			LATAbits.LATA3	//SCLK&lt;br /&gt;
#define PIN_A14			LATAbits.LATA14	//SDATA&lt;br /&gt;
&lt;br /&gt;
//send the AD9833 16 bits&lt;br /&gt;
void ad9833_set_freq(int value[]){&lt;br /&gt;
	 int i;&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 0;                          // set FSYNC pin low&lt;br /&gt;
	 for (i=0;i&amp;lt;=BITS16-1;i++){&lt;br /&gt;
	   PIN_A3 = 1;                        // set SCLK pin high&lt;br /&gt;
	   Delayms(1);&lt;br /&gt;
	     if (value[i] == 0){&lt;br /&gt;
	       PIN_A14 = 0;                   // set SDATA pin low&lt;br /&gt;
	     }&lt;br /&gt;
	     else {&lt;br /&gt;
	       PIN_A14 = 1;                   // set SDATA pin high&lt;br /&gt;
	     }&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	   PIN_A3 = 0;                        // set SCLK pin low&lt;br /&gt;
	   Delayms(1); &lt;br /&gt;
	 }&lt;br /&gt;
	 PIN_A3 = 1;                          // set SCLK pin high&lt;br /&gt;
	 PIN_A2 = 1;                          // set FSYNC pin high&lt;br /&gt;
	 Delayms(3);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to generate a wave from an ad9833 chip, we need to reset the chip and send a control bits to setup the type of wave. Then, we send lsb and msb of frequency register value, this value will saved in frequency register of the chip and will use it to calculate the actual frequency of the output wave. And then we have to un-reset the chip. This function does all this job for generating sine wave if you give a msb and lsb as its parameter.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void generateWave(int msb[], int lsb[]){&lt;br /&gt;
        int ad_sine[BITS16] = {0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; // reset the chip and set output to be a sine wave&lt;br /&gt;
	int unreset[BITS16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // unreset the ad9833 chip.&lt;br /&gt;
        ad9833_set_freq(ad_sine);&lt;br /&gt;
        ad9833_set_freq(lsb);&lt;br /&gt;
	ad9833_set_freq(msb);&lt;br /&gt;
	ad9833_set_freq(unreset);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The frequency of actual wave out of chip is calculated using the equation below and our master clock frequency, Fmclk is 20 MHZ. &lt;br /&gt;
                    fout = (Fmclk/2^28) * frequency register value.&lt;br /&gt;
More details on ad9833 chip can be found [http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI here].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Receiving Waves&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We will read two different sin waves from analog input B4 and B5. &lt;br /&gt;
* B4: Emitter wave&lt;br /&gt;
* B5: Receiver wave&lt;br /&gt;
We are using T3 timer interrupt to sample the emitter wave and receiver wave.  The sampling frequency of the timer is determined so it can actually reads 16 points in one cycle of the sin wave.  Therefore, we need 19 different sampling frequencies for all sine waves from 100HZ to 10KHZ.  With the PR value equation from lab4, we set our global int variable &amp;#039;samfreq&amp;#039; equal to PR values we calculated for each sampling frequencies.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void initInterruptController(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, samfreq); 	&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sampling Frequency and PR value for each reading frequency are provided in table below.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Reading Frequency!!Sampling Frequency!!PR Value(samfreq)&lt;br /&gt;
|-&lt;br /&gt;
|100||1600||0xC34F&lt;br /&gt;
|-&lt;br /&gt;
|200||3200||0x61A7&lt;br /&gt;
|-&lt;br /&gt;
|300||4800||0x411A&lt;br /&gt;
|-&lt;br /&gt;
|400||6400||0x30D3&lt;br /&gt;
|-&lt;br /&gt;
|500||8000||0x270F&lt;br /&gt;
|-&lt;br /&gt;
|600||9600||0x208D&lt;br /&gt;
|-&lt;br /&gt;
|700||11200||0x1BE6&lt;br /&gt;
|-&lt;br /&gt;
|800||12800||0x1869&lt;br /&gt;
|-&lt;br /&gt;
|900||14400||0x15B3&lt;br /&gt;
|-&lt;br /&gt;
|1000||16000||0x1387&lt;br /&gt;
|-&lt;br /&gt;
|2000||32000||0x09C3&lt;br /&gt;
|-&lt;br /&gt;
|3000||48000||0x0682&lt;br /&gt;
|-&lt;br /&gt;
|4000||64000||0x04E1&lt;br /&gt;
|-&lt;br /&gt;
|5000||80000||0x03E7&lt;br /&gt;
|-&lt;br /&gt;
|6000||96000||0x0341&lt;br /&gt;
|-&lt;br /&gt;
|7000||112000||0x02CA&lt;br /&gt;
|-&lt;br /&gt;
|8000||128000||0x0270&lt;br /&gt;
|-&lt;br /&gt;
|9000||144000||0x022B&lt;br /&gt;
|-&lt;br /&gt;
|10000||160000||0x01F3&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;FFT&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Good references and explanation for FFT calculation can be found in [http://hades.mech.northwestern.edu/index.php/PIC32MX:_FFT_of_Analog_Input here].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Interrupt Handlers *****************************************/&lt;br /&gt;
// interrupt the timer 3&lt;br /&gt;
void __ISR( _TIMER_3_VECTOR, ipl7) T3Interrupt( void)&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
        sampleBuffer1[sampleIndex].re = ReadADC10(0); // read the ADC from B4 into the real part&lt;br /&gt;
	sampleBuffer1[sampleIndex].im = ReadADC10(0); // read the ADC from B4 into the imaginary part&lt;br /&gt;
&lt;br /&gt;
	sampleBuffer2[sampleIndex].re = ReadADC10(1); // read the ADC from B5 into the real part&lt;br /&gt;
	sampleBuffer2[sampleIndex].im = ReadADC10(1); // read the ADC from B5 into the imaginary part&lt;br /&gt;
	&lt;br /&gt;
	// you could shave a little time off this ISR by just zeroing the .im value once, outside the ISR&lt;br /&gt;
&lt;br /&gt;
	// increment the sampleIndex&lt;br /&gt;
	if (sampleIndex == (N-1))&lt;br /&gt;
	{&lt;br /&gt;
		sampleIndex = 0;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&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;
} // T3 Interrupt&lt;br /&gt;
&lt;br /&gt;
void computeFFT()&lt;br /&gt;
{&lt;br /&gt;
	// when using 256 samples, we measured this function to take about 500 microseconds&lt;br /&gt;
	// (not including the time to send rs232 data)&lt;br /&gt;
	int i;&lt;br /&gt;
	&lt;br /&gt;
	// generate frequency vector&lt;br /&gt;
	// this is the x-axis of your single sided fft&lt;br /&gt;
	for (i=0; i&amp;lt;N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		freqVector[i] = i*(SAMPLEFREQ/2)/((N/2) - 1);&lt;br /&gt;
	}&lt;br /&gt;
	mT3IntEnable(0); //turns off interrupt while computing FFT&lt;br /&gt;
	&lt;br /&gt;
	//LOOP_TIME_PIN = TRUE;&lt;br /&gt;
	&lt;br /&gt;
	for (i=0; i&amp;lt;N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		if (i&amp;lt;sampleIndex)&lt;br /&gt;
		{&lt;br /&gt;
			// old chunk&lt;br /&gt;
			calcBuffer1[i+(N-sampleIndex)] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i+(N-sampleIndex)] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		else // i &amp;gt;= sampleIndex&lt;br /&gt;
		{&lt;br /&gt;
			// new chunk&lt;br /&gt;
			calcBuffer1[i-sampleIndex] = sampleBuffer1[i];&lt;br /&gt;
			calcBuffer2[i-sampleIndex] = sampleBuffer2[i];&lt;br /&gt;
		}	&lt;br /&gt;
		&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	// load complex input data into din&lt;br /&gt;
	mips_fft16(dout1, calcBuffer1, fftc, scratch1, log2N);&lt;br /&gt;
	mips_fft16(dout2, calcBuffer2, fftc, scratch2, log2N);	&lt;br /&gt;
&lt;br /&gt;
	// compute single sided fft&lt;br /&gt;
	for(i = 0; i &amp;lt; N/2; i++)&lt;br /&gt;
	{&lt;br /&gt;
		real[i] = dout1[i].re;&lt;br /&gt;
		imag[i] = dout1[i].im;&lt;br /&gt;
		real[i+N/2] = dout2[i].re;&lt;br /&gt;
		imag[i+N/2] = dout2[i].im;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
//	LOOP_TIME_PIN = FALSE;&lt;br /&gt;
	&lt;br /&gt;
	computeFFTflag = FALSE;&lt;br /&gt;
&lt;br /&gt;
	// do something with dout&lt;br /&gt;
	mT3IntEnable(1); //turn interrupt back on&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Control Motor&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We are using the interrupt handler for communicating with processing. The interrupt first checks which type of interrupt flag was generated (receive or transmit). If the interrupt was receive interrupt, it first reads the key pressed and echos it back to the terminal. It then goes into a switch statement depending on the letter. The letters are described below:&lt;br /&gt;
*&amp;#039;a&amp;#039; - make the motor moves an half inch&lt;br /&gt;
*&amp;#039;t&amp;#039; - start the system&lt;br /&gt;
*&amp;#039;u&amp;#039; - stop the motor move&lt;br /&gt;
*&amp;#039;v&amp;#039; - motor move forwards until stop requested&lt;br /&gt;
*&amp;#039;w&amp;#039; - motor move reverse until stop requested&lt;br /&gt;
*&amp;#039;x&amp;#039; - accelerate the speed of motor&lt;br /&gt;
*&amp;#039;y&amp;#039; - slow down the speed of motor&lt;br /&gt;
*&amp;#039;A&amp;#039; - stop the motor and sends all the data to plot graphs in the processing&lt;br /&gt;
*&amp;#039;c&amp;#039; - sends the motor to initial position&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// UART 2 interrupt handler&lt;br /&gt;
// it is set at priority level 2&lt;br /&gt;
void __ISR(_UART2_VECTOR, ipl2) IntUart2Handler(void)&lt;br /&gt;
{&lt;br /&gt;
	char data;&lt;br /&gt;
&lt;br /&gt;
	// Is this an RX interrupt?&lt;br /&gt;
	if(mU2RXGetIntFlag())&lt;br /&gt;
	{&lt;br /&gt;
		// Clear the RX interrupt Flag&lt;br /&gt;
		mU2RXClearIntFlag();&lt;br /&gt;
	&lt;br /&gt;
		data = ReadUART2();&lt;br /&gt;
		// Echo what we just received.&lt;br /&gt;
		putcUART2(data);&lt;br /&gt;
		&lt;br /&gt;
		switch(data)&lt;br /&gt;
		{	&lt;br /&gt;
			case &amp;#039;a&amp;#039;: // initialize&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;t&amp;#039;: // start&lt;br /&gt;
					start = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;u&amp;#039;: // stop&lt;br /&gt;
					start = FALSE;&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;v&amp;#039;: // forward&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Forward;&lt;br /&gt;
                                        keepmoving = TRUE;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;w&amp;#039;: // reverse&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
                                        keepmoving = FALSE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;x&amp;#039;: // accelerate&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed--;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;y&amp;#039;: // slow down&lt;br /&gt;
					//go = TRUE;&lt;br /&gt;
					speed++;&lt;br /&gt;
				break;	&lt;br /&gt;
			case &amp;#039;z&amp;#039;: // reset&lt;br /&gt;
					go = TRUE;&lt;br /&gt;
					DIR = Reverse;&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;A&amp;#039;: // activate&lt;br /&gt;
					go = FALSE;&lt;br /&gt;
					calcandplot();&lt;br /&gt;
				break;&lt;br /&gt;
			case &amp;#039;c&amp;#039;: // calibrate&lt;br /&gt;
					calibrate = TRUE;&lt;br /&gt;
				break;&lt;br /&gt;
		}			&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The codes below is the infinite while loop in main function of our code.&lt;br /&gt;
In order to move the sensor for a half inch 1288 steps are required for stepper motor.  So after 1288 steps, the motor will stop moving and it will start to read data.  After it sends data to processing, the motor start to move again.  For the stepper motor, if we generate the clock with shorter period will make the motor moves faster. So we are controlling the motor speed with Delayms(speed).  If the &amp;#039;speed&amp;#039; incremented, then the motor slows down and if the &amp;#039;speed&amp;#039; decremented, then the motor will accelerate.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	while(1) //2575 steps = 1 inch&lt;br /&gt;
	{&lt;br /&gt;
		if (calibrate == TRUE){    //calibrate button from process pressed&lt;br /&gt;
			dcalibrate();      //sends the motor to initial position&lt;br /&gt;
			calibrate = FALSE;&lt;br /&gt;
		}&lt;br /&gt;
		if (start == TRUE){		//Data acquisition button from process pressed&lt;br /&gt;
			while(go == TRUE) {	//activate button from process pressed&lt;br /&gt;
					CLK = 0;&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
					CLK = 1;	&lt;br /&gt;
					Delayms(speed);&lt;br /&gt;
						if(INPUT_A9 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 1;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						if(INPUT_A10 == FALSE){&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						step = 0;&lt;br /&gt;
						DIR = 0;&lt;br /&gt;
							while(step&amp;lt;200) {&lt;br /&gt;
							CLK=0;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							CLK=1;&lt;br /&gt;
							Delayms(speed);&lt;br /&gt;
							step++;&lt;br /&gt;
							}&lt;br /&gt;
						}&lt;br /&gt;
						//run it for 1288 steps and then stop&lt;br /&gt;
						if(step2&amp;gt;=1288) {&lt;br /&gt;
						step2 = 0;&lt;br /&gt;
						go = FALSE;&lt;br /&gt;
						halfinch++; &lt;br /&gt;
							    if(keepmoving==TRUE){&lt;br /&gt;
                                                  go = TRUE;&lt;br /&gt;
                                              }&lt;br /&gt;
						}&lt;br /&gt;
						step2++;&lt;br /&gt;
					}&lt;br /&gt;
			  //receive data, calculate fft, send data to processing&lt;br /&gt;
			  calcandplot();&lt;br /&gt;
			  go = TRUE;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
CloseOC1();&lt;br /&gt;
} //end main&lt;br /&gt;
&lt;br /&gt;
//sends the motor to initial position&lt;br /&gt;
void dcalibrate(){&lt;br /&gt;
	DIR = Reverse;&lt;br /&gt;
	while(INPUT_A10 == TRUE){&lt;br /&gt;
		CLK = 0;&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
		CLK = 1;	&lt;br /&gt;
		Delayms(speed);&lt;br /&gt;
	}&lt;br /&gt;
		step = 0;&lt;br /&gt;
		DIR = Forward;&lt;br /&gt;
		while(step&amp;lt;200) {&lt;br /&gt;
			CLK=0;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			CLK=1;&lt;br /&gt;
			Delayms(speed);&lt;br /&gt;
			step++;&lt;br /&gt;
		}&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Send to processing&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void sendDataRS232()&lt;br /&gt;
{&lt;br /&gt;
	int i;&lt;br /&gt;
	char RS232_Out_Buffer[128]; // max characters per line (line feed and carriage return count)&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;\n\rSTART\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;
	for(i = 0; i &amp;lt; N; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sprintf(RS232_Out_Buffer,&amp;quot;%d %d %d %d %d %d\n\r&amp;quot;,freqVector[i], calcBuffer1[i].re, &lt;br /&gt;
                calcBuffer2[i].re,  real[i], imag[i], halfinch); &lt;br /&gt;
		putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	sprintf(RS232_Out_Buffer,&amp;quot;END\n\r&amp;quot;); //output end so matlab knows we&amp;#039;re done&lt;br /&gt;
	putsUART2(RS232_Out_Buffer);&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
*[http://hades.mech.northwestern.edu/images/3/3c/Main.c Full version of C code]&lt;br /&gt;
&lt;br /&gt;
==Processing Code==&lt;br /&gt;
&lt;br /&gt;
The Processing code will display a window on the computer monitor that allows the user to control the motion of the linear actuator and sensor, run through a single routine of calculation and plotting, and run through full object identification and object detection routines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-window2.GIF | 400px]]  [[Image:team26-window.GIF | 400px]]&lt;br /&gt;
&lt;br /&gt;
The screenshot on the left is when it is currently calculating and plotting.  The screenshot on the right is after it has finished calculating and plotting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Sensing Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039;: returns the emitter/sensor board to the zero position.  Unless it is in the middle of calculating and plotting, the board will immediately head in the reverse direction until it hits the limit switch and then it will go forward 200 steps so that the limit switch is completely released.  All of our tests have been designed and analyzed according to and starting from this zero position.  Once the Calibrate button is pushed, this process cannot be stopped unless someone flips the PIC power switch or the +12V/-12V power switch, etc.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Activate&amp;#039;&amp;#039;&amp;#039;: activates the linear actuator so that the board can move&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Data Acquisition&amp;#039;&amp;#039;&amp;#039;: activates calculation and plotting (runs the Object Detection routine)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Calculate/Plot&amp;#039;&amp;#039;&amp;#039;: runs through a single routine of calculation and plotting, the board will not move after the bode plots are generated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Linear Actuator Control&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Note: for these buttons to have any effect, the &amp;quot;Activate&amp;quot; button needs to be pressed before these buttons&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Pause&amp;#039;&amp;#039;&amp;#039;: board will stop moving (if it was already moving)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Forward&amp;#039;&amp;#039;&amp;#039;: board will move forward (if not already moving forward) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Reverse&amp;#039;&amp;#039;&amp;#039;: board will move reverse (if not already moving reverse) at a constant speed&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Accelerate&amp;#039;&amp;#039;&amp;#039;: board will increase speed (by decreasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Slow&amp;#039;&amp;#039;&amp;#039;: board will decrease speed (by increasing the delay between clock pulses of the bipolar stepper motor by 1 ms)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Detection&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
*In order to run the Object Detection routine, you must press the &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; in sequence.&lt;br /&gt;
*&amp;quot;Data Acquisition&amp;quot; should be pressed first and &amp;quot;Activate&amp;quot; after.  The board will then perform calculations and plotting at its current position, then move a halfinch forward, and then repeat this process until it hits the limit switch at the end. &lt;br /&gt;
*If you press &amp;quot;Activate&amp;quot; first, then &amp;quot;Data Acquisition&amp;quot; after, the board will move a halfinch forward from its current position, perform calculations and plotting after it stops, and then it will repeat this process until it hits the limit switch at the end.  In this case, the step and location (according to the hashes) in the text file output will be off by 1 index.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Object Identification&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The Object Identification routine is performed automatically when &amp;quot;Data Acquisition&amp;quot; and &amp;quot;Activate&amp;quot; are pressed in sequence.  &lt;br /&gt;
*Once the board has stopped moving and all 19 magnitude and phase bode plot points have been calculated and plotted, the program will compare the bode plot with library of bode plots of different object type in which the object was directly underneath the sensor and display the object index of the object with the closest matching bode plot for magnitude and phase in the space between the buttons.  &lt;br /&gt;
*Thus, the program will try to identify whatever is underneath the sensor at its current position after each calculation and plotting routine (each time it has moved and stopped).&lt;br /&gt;
&lt;br /&gt;
===Window Contents===&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Emitted and sensed sinusoidal signals plots&amp;#039;&amp;#039;&amp;#039; - in the top left quadrant, these signals are plotted with horizontal guidelines that hit the maximum peak of the waves which also display the amplitude (mapped analog voltage values) so that you can visually compare and calculate the magnitude just by analyzing this plot. These signals also have vertical guidelines that hit the vertical mid point of both waves so that you can check the phase shift between the emitted and sensed waves.  The amplitude difference and phase shift is displayed in the top corners of the plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Magnitude plot&amp;#039;&amp;#039;&amp;#039; - the whole magnitude spectrum of the FFT of the emitted and sensed wave is plotted in the middle left quadrant.  There are vertical guidelines showing the frequency at the peak for both the emitted and sensed wave and what it should be (the frequency of waves we are sending out of the AD9833 function generator chip).  If the transfer function from the input (emitted wave) to the output (sensed wave) is linear, then there should only be a single peak in this plot.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;FFT Phase plot&amp;#039;&amp;#039;&amp;#039; - the whole phase spectrum of the FFT of the emitted and sensed wave is plotted in the bottom left quadrant.  The same vertical guidelines used in the FFT Magnitude plot are used here.&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Magnitude and Phase Bode plots&amp;#039;&amp;#039;&amp;#039; - an experimental magnitude and phase bode plot is plotted at 19 frequencies between 100Hz and 10kHz&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Display of Object Type and Object Location&amp;#039;&amp;#039;&amp;#039; - assuming that the sensor passes an object as it moves forward and runs through routines, program will run through an algorithm to determine where the object is according to the hashes on the back and what the object type is according to a bode plot library&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;Space for data display and debugging&amp;#039;&amp;#039;&amp;#039; - You can uncomment some portions of our code to display the values of arrays and variables on the empty right side of the window.  Currently, for a few seconds after a calculation and plotting routine (until the board finishes moving a halfinch), the program will display the 19 magnitude and phase points of the bode plot.  It also currently continuously displays many of the variables used in the calc() function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Code===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Description of Functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Our full Processing code is much too long to post here, so we will instead post a link here and at the end of this section to a zip file with the actual code with comments.  Some of the more important functions are posted.  Please note that you need to install the &amp;quot;ControlP5&amp;quot; custom GUI element library for Processing 1.0 by Andreas Schlegel in order for this Processing program to work.  The following section will describe what each function in our code does.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Download a zip file of our [[Media:final_electrosense.zip|Processing code]] and the [[Media:controlP5.zip|ControlP5 library]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;initserial()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Processing is set up so that it is continuously looking for data on the rs232 lines and once it sees data it will automatically start retrieving it.  Once the sensor has finished moving and fully stopped, the pic will send 5 arrays each with 512 data points to Processing.  The first set of arrays (data points) retrieved are of the 100 Hz voltage sinusoidal signals emitted and sensed.  &lt;br /&gt;
Next, there is a delay in the PIC, the sampling frequency is adjusted, the frequency of the signals is increased to 200 Hz, the fft of the signals is calculated, and then the next set of arrays corresponding to the 200 Hz wave is sent out and received by Processing.  This process is repeated until it goes through all 19 frequencies (100 Hz, 200 Hz, 300 Hz,…,10 kHz).&lt;br /&gt;
&lt;br /&gt;
*vector of frequencies (x axis) used to calculate the fft in the PIC, note that the first half (first 256 points) is nonzero, the second half is deleted (all zeros) in the PIC because it is essentially the same as the first half but in reverse order (256 frequency points + 256 zeros)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the emitted sinusoidal signal (512 emitted wave points)&lt;br /&gt;
&lt;br /&gt;
*y axis points of the sensed sinusoidal signal (512 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*real component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*imaginary component of the complex values resulting from the fft of both emitted and sensed signals.  First 256 points are of the emitted signal, second 256 points are of the sensed signal. (256 emitted wave points + 256 sensed wave points)&lt;br /&gt;
&lt;br /&gt;
*integer variable “finish” that corresponds to “halfinch” in the PIC code. (more on this below)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // grab the data&lt;br /&gt;
    if ((line_received.length == 6) &amp;amp;&amp;amp; (portNumber==0)){&lt;br /&gt;
      if (index &amp;gt;= L){&lt;br /&gt;
        index = 0;&lt;br /&gt;
        newdata = true;&lt;br /&gt;
        for (int i=0;i&amp;lt;L;i++) {&lt;br /&gt;
        sin1[i] = map(nsin1[i],min(nsin1)-300,max(nsin1)+300,-1*int(by*3/8),int(by*3/8));&lt;br /&gt;
        sin2[i] = map(nsin2[i],min(nsin2)-300,max(nsin2)+300,-1*int(by*3/8),int(by*3/8)); &lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      freq[index] = line_received[0];&lt;br /&gt;
      nsin1[index] = line_received[1];&lt;br /&gt;
      nsin2[index] = line_received[2];&lt;br /&gt;
      real[index] = line_received[3];&lt;br /&gt;
      imag[index] = line_received[4];&lt;br /&gt;
      &lt;br /&gt;
      if (line_received[5] &amp;gt; finish) {&lt;br /&gt;
        kk = 0;&lt;br /&gt;
        reinitializebp();&lt;br /&gt;
        finish = int(line_received[5]);&lt;br /&gt;
      }&lt;br /&gt;
      index++;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Note that we use this “newdata” Boolean variable to ensure that once we start collecting data points, we will finish collecting all 512 data points before we can use the data points for calculating and plotting in the other functions.&lt;br /&gt;
&lt;br /&gt;
*The sin1[] and sin2{} arrays collect the mapped nsin1[] and nsin2[] values respectively.  They are mapped according to the sine wave plotting window dimensions.&lt;br /&gt;
&lt;br /&gt;
*There is a corresponding integer variable to “finish” called “halfinch” in the PIC code that counts the 37 half-inches that the sensor/emitter board can move along the water tank.  It is incremented each time after the board moves a half-inch forward.  Right after the PIC finishes moving that half-inch, it needs to tell Processing that it is ready to start fft calculation and will begin to send data points over by sending this incremented “halfinch.”  Even though we just want to send “halfinch” over, when you send data via rs232, you must send all the information over.  So the PIC will first send out dummy data points plus an incremented “halfinch”.  It is compared to “finish,” “kk” is reset back to zero and the bode plots are cleared.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;global variables and setup()&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Some important variables:&lt;br /&gt;
&lt;br /&gt;
*int kk = 0; &lt;br /&gt;
frequency counter, kk is incremented by 1 each time draw() is run.  Once it reaches 19 (frequency of signals at 10 kHz), it set to 0 (frequency of signals at 100 Hz) again.&lt;br /&gt;
&lt;br /&gt;
*int L = 512; &lt;br /&gt;
total number of data points retrieved from PIC each time data is sent over.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;draw()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The sequence in which our functions are carried out is important.  &lt;br /&gt;
&lt;br /&gt;
*labels() is run to display labels&lt;br /&gt;
&lt;br /&gt;
*“newdata” allows us to run the rest of the functions only if we have finished getting all the data from the pic via rs232 and we have not reached the final 19th frequency&lt;br /&gt;
&lt;br /&gt;
*calc(), sinewaves(), fftmagplot(), and fftphaseplot() each have a Boolean variable “stepx” (x = 1 to 4, respectively) to ensure that the next function can only be run once the previous one has finished.  The Boolean variable “calculated” ensures that these first 4 functions have all finished before draw is run again; essentially “calculated” in draw() serves the same purpose as “newdata” in initserial().  &lt;br /&gt;
&lt;br /&gt;
*Once we reach the last frequency (kk reaches 19), bodecurve() and record() are run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void draw() {&lt;br /&gt;
  &lt;br /&gt;
  labels();  &lt;br /&gt;
  if (newdata == true &amp;amp;&amp;amp; kk&amp;lt;19) {&lt;br /&gt;
    if (calculated == false &amp;amp;&amp;amp; step4 == false) {&lt;br /&gt;
    delay(200);&lt;br /&gt;
    calc();   &lt;br /&gt;
    if(step1 == true) { sinewaves(); }&lt;br /&gt;
    if(step2 == true) { fftmagplot(); }&lt;br /&gt;
    if(step3 == true) { fftphaseplot(); }&lt;br /&gt;
    calculated = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(kk&amp;lt;19 &amp;amp;&amp;amp; calculated == true &amp;amp;&amp;amp; step4 == true) {&lt;br /&gt;
    calculated = false;&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    step1 = false;&lt;br /&gt;
    step2 = false;&lt;br /&gt;
    step3 = false;&lt;br /&gt;
    step4 = false;&lt;br /&gt;
    println(kk);&lt;br /&gt;
    kk++;&lt;br /&gt;
    }&lt;br /&gt;
    if (kk==19) {&lt;br /&gt;
    bodecurve();&lt;br /&gt;
    record();&lt;br /&gt;
    newdata = false;&lt;br /&gt;
    delay(100);&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;
&amp;#039;&amp;#039;&amp;#039;labels()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is full of text() functions used to display labels for the plots.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;calc()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*The data in real[] and imag[] arrays are split up into four 256 point arrays to carry the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
*The fft magnitude and phase points are calculated and stored in arrays.&lt;br /&gt;
&lt;br /&gt;
*The first fft magnitude point for both emitted and sensed sine waves arrays is ignored.&lt;br /&gt;
&lt;br /&gt;
*The index of the peak points of the fft magnitude arrays of the emitted and sensed waves are found.&lt;br /&gt;
&lt;br /&gt;
*The first 4 points on the emitted and sensed sine waves are averaged and stored in arrays to be used in plotting in sinewaves().&lt;br /&gt;
&lt;br /&gt;
*Two zero/mid points of both sinewaves are found to determine a single period (zero point to zero point) in both waves and the phase shift.&lt;br /&gt;
&lt;br /&gt;
*Display of variable and array values.&lt;br /&gt;
&lt;br /&gt;
*Records and plots the magnitude and phase bode plot points&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void calc()&lt;br /&gt;
{&lt;br /&gt;
  float zero1 = 0;&lt;br /&gt;
  float zero2 = 0;&lt;br /&gt;
  float max1 = 0; &lt;br /&gt;
  float max2 = 0; &lt;br /&gt;
  boolean foundzero1 = false;&lt;br /&gt;
  boolean foundzero2 = false;&lt;br /&gt;
  boolean foundzero1a = false;&lt;br /&gt;
  boolean foundzero2a = false;&lt;br /&gt;
  boolean foundzero1b = false;&lt;br /&gt;
  boolean foundzero2b = false;&lt;br /&gt;
        &lt;br /&gt;
  //first, the data in real[] and imag[] arrays are split up into four 256 point arrays to carry &lt;br /&gt;
  //the real and imaginary components of the complex fft values of the emitted and sensed waves.&lt;br /&gt;
  for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fftreal1[i] = real[i];        //real component of the fft of the emitted wave&lt;br /&gt;
  fftreal2[i] = real[i+L/2];    //real component of the fft of the sensed wave&lt;br /&gt;
  fftimag1[i] = imag[i];        //imaginary component of the fft of the emitted wave&lt;br /&gt;
  fftimag2[i] = imag[i+L/2];    //imaginary component of the fft of the sensed wave&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //fft1[] and fft2[] hold the magnitude of the emitted and sensed wave, respectively&lt;br /&gt;
  //fftphase1[] and fftphase2[] hold the phase of the emitted and sensed wave, respectively&lt;br /&gt;
	for (int i=0;i&amp;lt;L/2;i++) {&lt;br /&gt;
  fft1[i] = sqrt(fftreal1[i]*fftreal1[i] + fftimag1[i]*fftimag1[i]);&lt;br /&gt;
  fft2[i] = sqrt(fftreal2[i]*fftreal2[i] + fftimag2[i]*fftimag2[i]);&lt;br /&gt;
  fftphase1[i] = atan2(fftimag1[i], fftreal1[i])*180/PI;&lt;br /&gt;
  fftphase2[i] = atan2(fftimag2[i], fftreal2[i])*180/PI;&lt;br /&gt;
	}&lt;br /&gt;
  &lt;br /&gt;
  //the first data point in the fft magnitude tends to be very high and not important, so eliminate this first value&lt;br /&gt;
  //by putting them in new arrays (sfft1[] and sfft2[]) that don&amp;#039;t include the first value&lt;br /&gt;
  for (int i=0;i&amp;lt;(L/2)-1;i++)&lt;br /&gt;
	{&lt;br /&gt;
	sfft1[i] = fft1[i+1];&lt;br /&gt;
	sfft2[i] = fft2[i+1];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
  //finds the peak value the magnitude fft plot&lt;br /&gt;
	max1 = max(sfft1);&lt;br /&gt;
	max2 = max(sfft2);&lt;br /&gt;
  &lt;br /&gt;
  //finds the index of the peak value of the magnitude fft plot, the index (a and b) are used in the freq[] (frequency vector)&lt;br /&gt;
  //to find at what frequency this peak occurs&lt;br /&gt;
	for (int i=0;i&amp;lt;(L/2);i++) {&lt;br /&gt;
		if (fft1[i] == max1) {&lt;br /&gt;
			a = i;&lt;br /&gt;
		}	&lt;br /&gt;
		if (fft2[i] == max2) {&lt;br /&gt;
			b = i;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
 //averages that last 4 points in the sinusoidal signals and puts them in new arrays (msin1[] and msin2[])&lt;br /&gt;
 for (int i=0;i&amp;lt;L-3;i++) {&lt;br /&gt;
    msin1[i] = (sin1[i]+sin1[i+1]+sin1[i+2]+sin1[i+3])/4;&lt;br /&gt;
    msin2[i] = (sin2[i]+sin2[i+1]+sin2[i+2]+sin2[i+3])/4;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  //finds the mid point of the sine waves, note that this point is nonzero, the boolean variables &amp;quot;foundzero1&amp;quot; and &amp;quot;foundzero2&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  if(foundzero1 == false &amp;amp;&amp;amp; foundzero2 == false) {&lt;br /&gt;
  zero1 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  zero2 = min(msin1)+((max(msin1)-min(msin1))/2);&lt;br /&gt;
  foundzero1 = true;&lt;br /&gt;
  foundzero2 = true;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1a&amp;quot; and &amp;quot;foundzero2a&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a1&amp;quot; is the first zero point found on the emitted wave, &amp;quot;b1&amp;quot; is the first zero point found on the sensed wave&lt;br /&gt;
  for(int i=5;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a1 = i;&lt;br /&gt;
    foundzero1a = true;&lt;br /&gt;
    }&lt;br /&gt;
    if(foundzero2a == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b1 = i;&lt;br /&gt;
    foundzero2a = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //algorithm for finding the next zero/mid point of the sinewaves, the boolean variables &amp;quot;foundzero1b&amp;quot; and &amp;quot;foundzero2b&amp;quot;&lt;br /&gt;
  //are used to ensure that this calculation is not repeated again before this function has completed&lt;br /&gt;
  //&amp;quot;a2&amp;quot; is the index of the second and next zero point found on the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero1b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i+1]-zero1))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin1[i]-zero1)&amp;lt;=abs(msin1[i-1]-zero1))&amp;amp;&amp;amp;msin1[i-1]&amp;gt;msin1[i+1]) {&lt;br /&gt;
    a2 = i;&lt;br /&gt;
    foundzero1b = true;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  //&amp;quot;b2&amp;quot; is the index of the next zero point found on the sensed wave after &amp;quot;a2&amp;quot; of the emitted wave&lt;br /&gt;
  for(int i=(int)a1+2;i&amp;lt;L-3;i++) {&lt;br /&gt;
    if(foundzero2b == false&amp;amp;&amp;amp;(i+1&amp;lt;L-3)&amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i+1]-zero2))&lt;br /&gt;
    &amp;amp;&amp;amp;(abs(msin2[i]-zero2)&amp;lt;=abs(msin2[i-1]-zero2))&amp;amp;&amp;amp;msin2[i-1]&amp;gt;msin2[i+1]) {&lt;br /&gt;
    b2 = i;&lt;br /&gt;
    foundzero2b = true;&lt;br /&gt;
    }&lt;br /&gt;
  } &lt;br /&gt;
  &lt;br /&gt;
   //u2 is the period, note that u2 is always calculated to be 16  &lt;br /&gt;
   //we are forcing &amp;quot;a2&amp;quot; to come after (on the right side of) &amp;quot;b2&amp;quot;&lt;br /&gt;
   u2 = a2-a1;&lt;br /&gt;
   while(b2-a2&amp;gt;u2) { b2=b2-u2; }&lt;br /&gt;
  &lt;br /&gt;
  //magnitude and phase calculations&lt;br /&gt;
  //&amp;quot;magnitude,&amp;quot; &amp;quot;abs_phase,&amp;quot; and &amp;quot;phase_pic&amp;quot; are calculated from the fft&lt;br /&gt;
  //&amp;quot;wave_mag,&amp;quot; &amp;quot;phase&amp;quot; and &amp;quot;phase_u2&amp;quot; are calculated from looking at the sine waves&lt;br /&gt;
  //unfortunately, magnitude_pic wouldn&amp;#039;t work anyway since the &amp;quot;i (or j)&amp;quot; is eliminated, &lt;br /&gt;
  //the imaginary component would just combine with the real component when added in the transfer function. &lt;br /&gt;
  &lt;br /&gt;
  magnitude = max2/max1;&lt;br /&gt;
  abs_phase = fftphase2[b]-fftphase1[a];&lt;br /&gt;
  phase_u2 = (b2-a2)/u2*360;&lt;br /&gt;
  if(phase_u2 &amp;lt;-360) {phase_u2=phase_u2+360;}&lt;br /&gt;
  &lt;br /&gt;
  phase = phase_u2;&lt;br /&gt;
  //magnitude = max(nsin2)/max(nsin1);&lt;br /&gt;
  //magnitude_pic = abs((fftreal2[b]+fftimag2[b])/(fftreal1[a]+fftimag1[a]));&lt;br /&gt;
  phase_pic = 180+atan2((fftreal2[b]+fftimag2[b]),(fftreal1[a]+fftimag1[a]))*180/PI;&lt;br /&gt;
  &lt;br /&gt;
  //the frequency of the peak in the magnitude fft plot, &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot; should be equal and so just &amp;quot;a&amp;quot; is used&lt;br /&gt;
  freq1 = freq[a];&lt;br /&gt;
  &lt;br /&gt;
  //displaying some of the calculation results&lt;br /&gt;
  fill(0);&lt;br /&gt;
  noStroke();&lt;br /&gt;
  rect(width-100,0,100,200);&lt;br /&gt;
  fill(255);&lt;br /&gt;
  text(&amp;quot;abs_mag &amp;quot;+(float)magnitude,width-90,9);&lt;br /&gt;
  text(&amp;quot;abs_phase &amp;quot;+abs_phase,width-90,18);&lt;br /&gt;
  text(&amp;quot;tf_mag &amp;quot;+(int)magnitude_pic,width-90,27);&lt;br /&gt;
  text(&amp;quot;tf_phase &amp;quot;+phase_pic,width-90,36);&lt;br /&gt;
  text(&amp;quot;exp_freq &amp;quot;+(int)freq1,width-90,45);&lt;br /&gt;
  text(&amp;quot;act_freq &amp;quot;+(int)freq2[kk],width-90,54);&lt;br /&gt;
  text(&amp;quot;wave_mag &amp;quot;+(int)(max(nsin2)/max(nsin1)),width-90,63);&lt;br /&gt;
  text(&amp;quot;u2 &amp;quot;+(int)u2,width-90,72);&lt;br /&gt;
  text(&amp;quot;phase_u2 &amp;quot;+(float)phase,width-90,81);&lt;br /&gt;
  text(&amp;quot;a1 &amp;quot;+a1,width-90,90);&lt;br /&gt;
  text(&amp;quot;b1 &amp;quot;+b1,width-90,99);&lt;br /&gt;
  text(&amp;quot;a2 &amp;quot;+(int)a2,width-90,108);&lt;br /&gt;
  text(&amp;quot;b2 &amp;quot;+(int)b2,width-90,117);&lt;br /&gt;
  text(&amp;quot;finish &amp;quot;+finish,width-90,126);&lt;br /&gt;
  &lt;br /&gt;
  //initializing expected frequency values in freq2[]&lt;br /&gt;
  freq2[0] = 100;&lt;br /&gt;
  freq2[1] = 200;&lt;br /&gt;
  freq2[2] = 300;&lt;br /&gt;
  freq2[3] = 400;&lt;br /&gt;
  freq2[4] = 500;&lt;br /&gt;
  freq2[5] = 600;&lt;br /&gt;
  freq2[6] = 700;&lt;br /&gt;
  freq2[7] = 800;&lt;br /&gt;
  freq2[8] = 900;&lt;br /&gt;
  freq2[9] = 1000;&lt;br /&gt;
  freq2[10] = 2000;&lt;br /&gt;
  freq2[11] = 3000;&lt;br /&gt;
  freq2[12] = 4000;&lt;br /&gt;
  freq2[13] = 5000;&lt;br /&gt;
  freq2[14] = 6000;&lt;br /&gt;
  freq2[15] = 7000;&lt;br /&gt;
  freq2[16] = 8000;&lt;br /&gt;
  freq2[17] = 9000;&lt;br /&gt;
  freq2[18] = 10000;&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the magnitude bode plot&lt;br /&gt;
  float bwidth = bx-bx/5;&lt;br /&gt;
  float bheight = by-by/4;&lt;br /&gt;
  float x0 = bx+bx/10;&lt;br /&gt;
  float ya = by/2;&lt;br /&gt;
  float dy = map(20*log(magnitude)/log(10),-100, 100, -1*bheight/2, bheight/2);&lt;br /&gt;
  float dx = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  stroke(0,0,128);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx, ya-dy);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //plotting points on the phase bode plot&lt;br /&gt;
  //float bwidth = bx-bx/5;&lt;br /&gt;
  //float bheight = by-by/4;&lt;br /&gt;
  //float x0 = bx+bx/10;&lt;br /&gt;
  float yb = by*3/2;&lt;br /&gt;
  float dx0 = map((log(freq2[kk])/log(10))-2,0,2,0,bwidth);&lt;br /&gt;
  float dy0 = map(phase, -450, 450, -1*bheight/2, bheight/2);&lt;br /&gt;
  stroke(255,0,0);&lt;br /&gt;
  strokeWeight(3);&lt;br /&gt;
  point(x0+dx0, yb-dy0);&lt;br /&gt;
  strokeWeight(1);&lt;br /&gt;
  &lt;br /&gt;
  //recording the magnitude and phase bode plot points of the current frequency&lt;br /&gt;
  recmag[kk] = magnitude;&lt;br /&gt;
  recphase[kk] = phase;&lt;br /&gt;
&lt;br /&gt;
  //uncomment to display array values on the right side of the window, &lt;br /&gt;
  //you can change the array variable and how many points in the array you want to see&lt;br /&gt;
  //right now we are displaying the first 128 points of the emitted and sensed sine waves&lt;br /&gt;
  /*        &lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   rect(2*bx,8*k,220,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(sin1[k],2*bx,8*k);&lt;br /&gt;
   text(sin1[k+64],2*bx+50,8*k);&lt;br /&gt;
   text(sin2[k],2*bx+100,8*k);&lt;br /&gt;
   text(sin2[k+64],2*bx+150,8*k);&lt;br /&gt;
 }&lt;br /&gt;
   for (int k=0;k&amp;lt;=64;k++) { &lt;br /&gt;
   fill(0);&lt;br /&gt;
   noStroke();&lt;br /&gt;
   //rect(2*bx+150,8*k,10,8);&lt;br /&gt;
   fill(255);&lt;br /&gt;
   text(k,2*bx+200,8*k);&lt;br /&gt;
 }&lt;br /&gt;
 */&lt;br /&gt;
 step1 = true; //completed calc()&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;sinewaves()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots the voltage sine waves of the emitted and sensed signals.&lt;br /&gt;
&lt;br /&gt;
*Displays vertical guidelines that hit the zero point measured in the emitted and sensed sine waves.&lt;br /&gt;
&lt;br /&gt;
*Displays a horizontal guideline that hits the peak of the sine waves and displays the value of the peak of both emitted and sensed waves.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftmagplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft magnitude with vertical guidelines hitting the peak point which are the actual, calculated frequency of the emitted and sensed waves.  There is also a vertical guideline for the expected frequency of the emitted and sensed waves.  These frequency values should be equal at all times, but you will see that the actual frequencies deviate from the expected frequency a little.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;fftphaseplot()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Plots a curve of the fft phase with vertical guidelines of the actual, calculated frequency of the emitted and sensed waves.  These are the same guidelines in fftmagplot().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bodecurve()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*This function is run after all 19 different frequency sine waves are sent from the PIC and plotted.  The main purposes of this function are to connect the magnitude and phase bode plot points plotted in calc() with a curve line and to display the magnitude and phase values at each frequency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;reinitializebp()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Clears the bode plots&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;record()&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
*Object identification algorithm code and object detection algorithm code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
float logmag = 0;&lt;br /&gt;
 float where = map(finish,0,37,2.36,20.64);&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_m = 0;&lt;br /&gt;
 float compare_acrylic_m = 0;&lt;br /&gt;
 float compare_iron_m = 0; &lt;br /&gt;
 float compare_aluminum_m = 0;&lt;br /&gt;
 float compare_plastic_m = 0;&lt;br /&gt;
 float compare_grape_m = 0;&lt;br /&gt;
 &lt;br /&gt;
 float compare_water_p = 0;&lt;br /&gt;
 float compare_acrylic_p = 0;&lt;br /&gt;
 float compare_iron_p = 0; &lt;br /&gt;
 float compare_aluminum_p = 0;&lt;br /&gt;
 float compare_plastic_p = 0;&lt;br /&gt;
 float compare_grape_p = 0;&lt;br /&gt;
   &lt;br /&gt;
   //computing the sum of the absolute value of the differences&lt;br /&gt;
 for(int i=0;i&amp;lt;10;i++) {&lt;br /&gt;
   compare_acrylic_m = compare_acrylic_m + abs(acrylic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_water_m = compare_water_m + abs(water_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_grape_m = compare_grape_m + abs(grape_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_iron_m = compare_iron_m + abs(iron_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_plastic_m = compare_plastic_m + abs(plastic_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   compare_aluminum_m = compare_aluminum_m + abs(aluminum_m[i] - 20*log(recmag[i+9])/log(10));&lt;br /&gt;
   &lt;br /&gt;
   compare_acrylic_p = compare_acrylic_p + abs(acrylic_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_aluminum_p = compare_aluminum_p + abs(aluminum_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_grape_p = compare_grape_p + abs(grape_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_water_p = compare_water_p + abs(water_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_iron_p = compare_iron_p + abs(iron_p[i] - recphase[i+9]);&lt;br /&gt;
   compare_plastic_p = compare_plastic_p + abs(plastic_p[i] - recphase[i+9]);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 float[] identify_m = new float[6];&lt;br /&gt;
 float[] identify_p = new float[6];&lt;br /&gt;
 &lt;br /&gt;
   //dividing by 10 to get the average&lt;br /&gt;
  identify_m[0] = compare_water_m/10;&lt;br /&gt;
  identify_m[1] = compare_acrylic_m/10;&lt;br /&gt;
  identify_m[2] = compare_iron_m/10;&lt;br /&gt;
  identify_m[3] = compare_aluminum_m/10;&lt;br /&gt;
  identify_m[4] = compare_plastic_m/10;&lt;br /&gt;
  identify_m[5] = compare_grape_m/10;&lt;br /&gt;
 &lt;br /&gt;
  identify_p[0] = compare_water_p/10;&lt;br /&gt;
  identify_p[1] = compare_acrylic_p/10;&lt;br /&gt;
  identify_p[2] = compare_iron_p/10; &lt;br /&gt;
  identify_p[3] = compare_aluminum_p/10;&lt;br /&gt;
  identify_p[4] = compare_plastic_p/10;&lt;br /&gt;
  identify_p[5] = compare_grape_p/10;&lt;br /&gt;
  &lt;br /&gt;
  //finding which array had the smallest average, by putting all 6 object type averages into 2 arrays, &lt;br /&gt;
  //&amp;quot;identify_m&amp;quot; (for magnitude) and &amp;quot;identify_p&amp;quot; (for phase), respectively.&lt;br /&gt;
  //then we find the minimum of the 2 arrays using min() and put that value into &amp;quot;choose_m&amp;quot; (for magnitude)&lt;br /&gt;
  //and &amp;quot;choose_p&amp;quot; (for phase).  a for loop is used to run through the values of the &amp;quot;identify_m&amp;quot; and &amp;quot;identify_p&amp;quot; arrays&lt;br /&gt;
  //until there is a match between &amp;quot;choose_m&amp;quot; and &amp;quot;identify_m[i]&amp;quot; and &amp;quot;choose_p&amp;quot; and &amp;quot;identify_p[i]&amp;quot; where &amp;quot;i&amp;quot; is the index&lt;br /&gt;
  //of the arrays.  the index &amp;quot;i&amp;quot; then determines the object type, one for magnitude and one for phase.&lt;br /&gt;
  float choose_m = min(identify_m);&lt;br /&gt;
  float choose_p = min(identify_p);&lt;br /&gt;
  float identify1 = 0;&lt;br /&gt;
  float identify2 = 0;&lt;br /&gt;
  &lt;br /&gt;
  for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_m == identify_m[i]) {&lt;br /&gt;
     identify1 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
    for(int i=0;i&amp;lt;6;i++) {&lt;br /&gt;
   if(choose_p == identify_p[i]) {&lt;br /&gt;
     identify2 = i;&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  text(&amp;quot;0: water, no object&amp;quot;,bx+bx/10,by*2+101);&lt;br /&gt;
  text(&amp;quot;1: acrylic&amp;quot;,bx+bx/10,by*2+110);&lt;br /&gt;
  text(&amp;quot;2: iron&amp;quot;,bx+bx/10,by*2+119);&lt;br /&gt;
  text(&amp;quot;3: aluminum&amp;quot;,bx+bx/10,by*2+128);&lt;br /&gt;
  text(&amp;quot;4: plastic&amp;quot;,bx+bx/10,by*2+137);&lt;br /&gt;
  text(&amp;quot;5: grape&amp;quot;,bx+bx/10,by*2+146);&lt;br /&gt;
  &lt;br /&gt;
  noStroke();&lt;br /&gt;
  fill(0);&lt;br /&gt;
  rect(bx+bx/10,by*2+63,200,27);&lt;br /&gt;
  fill(255);m&lt;br /&gt;
  text(&amp;quot;object type (derived from magnitude): &amp;quot;+int(identify1),bx+bx/10,by*2+72);&lt;br /&gt;
  text(&amp;quot;object type (derived from phase): &amp;quot;+int(identify2),bx+bx/10,by*2+81);&lt;br /&gt;
   &lt;br /&gt;
   &lt;br /&gt;
   //the following code describes how we determine where the object is in the water tank (object detection)&lt;br /&gt;
   //the object detection algorithm is as follows:&lt;br /&gt;
   //assuming that the object is placed somewhere in the tank along the path of the emitter/sensor board &lt;br /&gt;
   //and not shifted out perpendicularly from the board and the board has scanned at least a length &lt;br /&gt;
   //covering a distance starting before reaching the object (at least 1 halfinch before), directly &lt;br /&gt;
   //above the object, and after moving past the object (at least 1 halfinch after),&lt;br /&gt;
   //experimental results have shown that all magnitude bode plot curves, especially at higher &lt;br /&gt;
   //frequencies, will continue or start to decrease, but when the board is directly above the object, &lt;br /&gt;
   //the magnitude bode plot curve will have the greatest values.  we find the curve with the maximum &lt;br /&gt;
   //magnitude bode plot points and then look at where we are in the tank by counting many times we have &lt;br /&gt;
   //moved (each time we move, we move a halfinch) to determine the object location.&lt;br /&gt;
   &lt;br /&gt;
   //each time this program is run, it creates a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this &lt;br /&gt;
   //sketch is located and records the step (how many halfinches the board has moved), location (where &lt;br /&gt;
   //the board is according to the hashes etched on the back of the water tank), frequency (of voltage &lt;br /&gt;
   //sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency)&lt;br /&gt;
   for (int k=0;k&amp;lt;19;k++) {&lt;br /&gt;
     logmag = 20*log(recmag[k])/log(10);&lt;br /&gt;
   output.println(&amp;quot;step: &amp;quot;+nf(finish,2,0)+&amp;quot; | location: &amp;quot;+nf(where,2,2)+&amp;quot; | frequency: &amp;quot;+nf(freq2[k],5,0)+&amp;quot; &lt;br /&gt;
    | magnitude: &amp;quot;+nfp(logmag,2,3)+ &amp;quot; | phase: &amp;quot; +nfp(recphase[k],3,1)); &lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   //since all magnitude bode plots decrease in magnitude and each magnitude point is either 0dB or less, &lt;br /&gt;
   //at the current position, we take the absolute value of each magnitude (dB) point (0Hz to 10kHz), &lt;br /&gt;
   //then take the average, and if the current average of the current position is less than the previous &lt;br /&gt;
   //average at a previous position, we have found that the object is directly below the board.&lt;br /&gt;
   for(int k=1;k&amp;lt;19;k++){&lt;br /&gt;
       currentAvg = currentAvg + abs(20*log(recmag[k])/log(10));&lt;br /&gt;
     }&lt;br /&gt;
      currentAvg = currentAvg/19;&lt;br /&gt;
      println(&amp;quot;currentAvg&amp;quot;);&lt;br /&gt;
      println(currentAvg);&lt;br /&gt;
      //currentAvg = abs(k);&lt;br /&gt;
      if (currentAvg &amp;lt; prevAvg){&lt;br /&gt;
          prevAvg = currentAvg; &lt;br /&gt;
          location = where;&lt;br /&gt;
          println(&amp;quot;location&amp;quot;);&lt;br /&gt;
          println(location);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      text(&amp;quot;object @ &amp;quot;+location+&amp;quot; inches&amp;quot;,bx+bx/10,by*2+90);&lt;br /&gt;
      &lt;br /&gt;
    output.println(&amp;quot; &amp;quot;);&lt;br /&gt;
    output.flush();&lt;br /&gt;
     if (finish &amp;gt;=37) { // Writes the remaining data to the file&lt;br /&gt;
     output.close(); // Finishes the file&lt;br /&gt;
     }&lt;br /&gt;
     smooth();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Each time this function is run, it creates or appends data to a text file (&amp;quot;bodeplotdata.txt&amp;quot;) in the folder where this sketch is located and records the step (how many halfinches the board has moved), location (where the board is according to the hashes etched on the back of the water tank), frequency (of voltage sine waves sent out), magnitude (in dB, at each frequency), and phase (in degrees, at each frequency).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Test Results and Analysis=&lt;br /&gt;
&lt;br /&gt;
In the limited time between getting our circuit to function correctly with the Processing program and demostrating our project, we were only able to run a number of trials scanning past different objects to determine object type and object location.  Our test results seem to indicate some trends but we cannot make any firm conclusions because this is only a first pass of experiments, hopefully the results obtained thus far will warrant future research.&lt;br /&gt;
&lt;br /&gt;
==Experimental Dimensions==&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-diagram.GIF | 300px]]   [[Image:team26-diagram2.GIF | 250px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Water tank measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Emitter/sensor board = square with equal length and width = 3.19in / 81.02mm&lt;br /&gt;
&lt;br /&gt;
Distance from floor to emitter/sensor board = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
Distance from center of board to side of water tank = 3.13in / 79.50mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bipolar stepper motor measurements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1 inch (25.4mm): 2576 steps&lt;br /&gt;
&lt;br /&gt;
full distance of water tank the board can traverse (limit switch to limit switch) = 18.5 inches (470mm)&lt;br /&gt;
&lt;br /&gt;
full distance in steps = 47656 steps&lt;br /&gt;
&lt;br /&gt;
37 full halfinches in 18.5 inches (full distance)&lt;br /&gt;
&lt;br /&gt;
1 halfinch (12.7mm) = 1288 steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Aluminum&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.25in / 31.69mm&lt;br /&gt;
&lt;br /&gt;
W = 0.58in / 14.76mm&lt;br /&gt;
&lt;br /&gt;
D = 0.36in / 9.15mm&lt;br /&gt;
&lt;br /&gt;
H = 2.77in / 70.29mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Iron&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 31.88mm&lt;br /&gt;
&lt;br /&gt;
W = 0.96in / 24.32mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.84mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.60mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Acrylic&amp;#039;&amp;#039;&amp;#039; (flipped so that the well is on the bottom facing the floor)&lt;br /&gt;
&lt;br /&gt;
L = 1.26in / 32.00mm&lt;br /&gt;
&lt;br /&gt;
W = 0.99in / 25.10mm&lt;br /&gt;
&lt;br /&gt;
D = 0.80in / 20.54mm&lt;br /&gt;
&lt;br /&gt;
H = 2.33in / 58.9mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Plastic&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
L = 1.36in / 34.62mm&lt;br /&gt;
&lt;br /&gt;
W = 0.76in / 19.24mm&lt;br /&gt;
&lt;br /&gt;
D = 0.39in / 9.93mm&lt;br /&gt;
&lt;br /&gt;
H = 2.74in / 69.51mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Grape on acrylic block&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
One grape was put in the small well etched on the top face of the acrylic block.&lt;br /&gt;
&lt;br /&gt;
Grapes were approximately 20mm diameter spheres.&lt;br /&gt;
&lt;br /&gt;
D = 0.393in / 10mm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Diameter (L and W) = 1.75in / 44.61mm&lt;br /&gt;
&lt;br /&gt;
D = 0.52in / 13.25mm&lt;br /&gt;
&lt;br /&gt;
H = 2.61in / 66.19mm&lt;br /&gt;
&lt;br /&gt;
==Test Results==&lt;br /&gt;
[[Image:team26-dom.GIF | 450px]]  [[Image:team26-dop.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots for different objects with the sensor directly above the object.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
 &lt;br /&gt;
Aluminum seems to have a characteristic response significantly different than the other objects.&lt;br /&gt;
&lt;br /&gt;
For this experiment, all objects were placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:different_objects.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-middlem.GIF | 450px]]  [[Image:team26-middlep.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Especially at higher frequencies (4kHz to 10kHz), the magnitude values are the greatest when the sensor is directly above the brass cylinder. &lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.00in / 0.00mm&lt;br /&gt;
&lt;br /&gt;
B = 1.48in / 37.60mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:team26-shiftm.GIF | 450px]]  [[Image:team26-shiftp.GIF | 450px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Bode plots as the sensor moves past a brass cylinder shifted off to the side&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
There is a big jump and plateau for several frequencies in the 3 phase bode plot curves where the sensor is near the object.&lt;br /&gt;
&lt;br /&gt;
For this experiment, the brass cylinder was placed in the water tank approximately at these specifications&lt;br /&gt;
&lt;br /&gt;
A = 0.80in / 20.00mm&lt;br /&gt;
&lt;br /&gt;
B = 4.45in / 113.07mm&lt;br /&gt;
&lt;br /&gt;
The recorded data and excel plots can be found [[Media:brass_cylinder.zip|here]].&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-AD9833_circuit.jpg&amp;diff=17274</id>
		<title>File:TR JP PP-AD9833 circuit.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:TR_JP_PP-AD9833_circuit.jpg&amp;diff=17274"/>
		<updated>2010-03-17T07:02:07Z</updated>

		<summary type="html">&lt;p&gt;JamesReynolds: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JamesReynolds</name></author>
	</entry>
</feed>