<?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=JeremyDarling</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=JeremyDarling"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php/Special:Contributions/JeremyDarling"/>
	<updated>2026-05-01T02:23:11Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.9</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8642</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8642"/>
		<updated>2008-03-21T08:19:53Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|350px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Explanation ===&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
=== Other features ===&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
=== PIC Inputs ===&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
=== PIC Outputs ===&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Circuit Components ===&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Parts List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
=== Modular Code ===&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Code ===&lt;br /&gt;
&lt;br /&gt;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8641</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8641"/>
		<updated>2008-03-21T08:19:30Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|300px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Explanation ===&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
=== Other features ===&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
=== PIC Inputs ===&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
=== PIC Outputs ===&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Circuit Components ===&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Parts List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
=== Modular Code ===&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Code ===&lt;br /&gt;
&lt;br /&gt;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8640</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8640"/>
		<updated>2008-03-21T08:19:02Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|250px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Explanation ===&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
=== Other features ===&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
=== PIC Inputs ===&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
=== PIC Outputs ===&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Circuit Components ===&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Parts List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
=== Modular Code ===&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Code ===&lt;br /&gt;
&lt;br /&gt;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8639</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8639"/>
		<updated>2008-03-21T08:17:26Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|250px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Explanation ===&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
=== Other features ===&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
=== Circuit Components ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Parts List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
=== Modular Code ===&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Code ===&lt;br /&gt;
&lt;br /&gt;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8637</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8637"/>
		<updated>2008-03-21T08:15:33Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|250px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
=== Circuit Components ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Parts List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
=== Modular Code ===&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Code ===&lt;br /&gt;
&lt;br /&gt;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8636</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8636"/>
		<updated>2008-03-21T08:15:13Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|2500px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
=== Circuit Components ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Parts List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
=== Modular Code ===&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Code ===&lt;br /&gt;
&lt;br /&gt;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8634</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8634"/>
		<updated>2008-03-21T08:10:41Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|200px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
=== Circuit Components ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Parts List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
=== Modular Code ===&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Code ===&lt;br /&gt;
&lt;br /&gt;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8632</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8632"/>
		<updated>2008-03-21T08:08:07Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Software Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|200px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
=== Modular Code ===&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Code ===&lt;br /&gt;
&lt;br /&gt;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8631</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8631"/>
		<updated>2008-03-21T08:07:15Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Software Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|200px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Code ===&lt;br /&gt;
&lt;br /&gt;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8629</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8629"/>
		<updated>2008-03-21T08:05:07Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|200px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8613</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8613"/>
		<updated>2008-03-21T07:53:16Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Future Action */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|200px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results and Reflections==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different [http://en.wikipedia.org/wiki/Touchscreen#Technologies type of touchscreen] could be used, such as an infrared touchscreen.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8609</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8609"/>
		<updated>2008-03-21T07:49:25Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Results and Reflections */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|200px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Faulhaber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://ww1.microchip.com/downloads/en/DeviceDoc/39631D.pdf PIC18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ortodoxism.ro/datasheets/texasinstruments/l293d.pdf L293D] &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.ti.com/lit/gpn/sn74hc04 SN74HC04]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.bergquistcompany.com/objects/touch_drawings/DRW_TS_400206_123rev.pdf BER237-ND]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results and Reflections==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Moves the motor to a pre-defined angle&lt;br /&gt;
void GoToAngle(int xangle,int yangle) {&lt;br /&gt;
   while ((Encoder1 &amp;lt; (angleref[xangle]-100)) &amp;amp;&amp;amp; (Encoder1 &amp;gt; (angleref[xangle]+100)) ) {      &lt;br /&gt;
      if (Encoder1&amp;lt;angleref[xangle]) set_pwm1_duty(78);&lt;br /&gt;
      if (Encoder1&amp;gt;angleref[xangle]) set_pwm1_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   while ((Encoder2 &amp;gt; (angleref[yangle]-100)) &amp;amp;&amp;amp; (Encoder2 &amp;gt; (angleref[yangle]+100)) ) {          &lt;br /&gt;
      if (Encoder2&amp;lt;angleref[yangle]) set_pwm2_duty(78);&lt;br /&gt;
      if (Encoder2&amp;gt;angleref[yangle]) set_pwm2_duty(0);&lt;br /&gt;
   }&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int angleref[51] = {0, 91, 182, 273, 364, 455, 546, 637, 728, 819, 910, 1000, 1091, 1182, 1273, 1364, 1455, 1546, 1637, 1728, 1819, 1910, &lt;br /&gt;
                     2001, 2091, 2182, 2273, 2364, 2455, 2546, 2637, 2727, 2818, 2909, 3000, 3091, 3181, 3272, 3363, 3454, 3545, 3635, 3726, &lt;br /&gt;
                      3817, 3907, 3998, 4089, 4179, 4270, 4361, 4451, 4542}; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first box is the function that takes a desired x-angle and a desired y-angle and tells the motor to move to that position as fast as possible. The angles passed to the function are actually a value 10 times the angle (e.g. to move the screen to 2.5 degrees on the x-axis and 3.7 on the y-axis one would type &amp;lt;pre&amp;gt;GoToAngle(25,37)&amp;lt;/pre&amp;gt;). The second box is an array containing the encoder values associated with the the angle of one tenth of their index. For example, to encrease a tilt by 1.0 degrees, the encoder count would have to increase by the value of angleref[10], which is 910.&lt;br /&gt;
&lt;br /&gt;
The main problem with using this method was that we were having hard times reading the encoders, and it was very difficult to manually make the screen flat before every use, as would be necessary for this to work, as there was no other way to establish a base encounter count.&lt;br /&gt;
&lt;br /&gt;
Finally, the big problem we needed to tackle was a way to get a more consistent reading from the touchscreen, as this method led to a lot of false zeros. Putting a simple analog RC low pass filter did not work because the speed at which the PIC sampled the signal was too high, and the shaping of the curve would throw off the readings. A more complex analog filter might have improved this situation, but we chose to instead explore software filters. The software filters were moderately more successful, but they weren&amp;#039;t perfect and they caused our code to severely lack resolution in the readings, as too many of the values were thrown out. The problem might be fixed mechanically if a game piece with a higher friction coefficient were used than the steel ball, such as a square slider. Alternatively, a different type of touchscreen could be used, such as an [http://en.wikipedia.org/wiki/Touchscreen#Infrared infrared touchscreen].&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=8596</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=8596"/>
		<updated>2008-03-21T07:20:46Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* ME 333 Final Projects 2008 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;[[ME 333 end of course schedule]]&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&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. [http://depot.northwestern.edu/mht363/public_html/IR%20Track/Mar%2019%20IR%20tracker.mp4 See Spot Run.]&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;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake]&lt;br /&gt;
&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_setup1.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;
&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>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8580</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8580"/>
		<updated>2008-03-21T06:40:47Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|200px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering MS 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two [http://hades.mech.northwestern.edu/wiki/index.php/Potentiometers potentiometers]) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Faulhaber_1524E006S_motor_with_141:1_gearhead_and_HES164A_magnetic_quadrature_encoder Falhauber motors] mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  [[Image:Coinslotopen.JPG|left|thumb|Coinslot with top off|200px]] Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame). By controlling the speed of the motors via [http://hades.mech.northwestern.edu/wiki/index.php/Pulse_Width_Modulation pulse width modulation], the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors, LED &amp;quot;strike&amp;quot; array, and buzzer. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
[[Image:TouchscreenControlpanel.JPG|left|thumb|Touch screen controls and LED display|200px]]&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
Toggle switches were added to allow easy powering on and off of our system. Also, a switch for automatic and manual control was implemented which was designed to have the purpose of switching the design from joystick control to automatic system control (self-adjusting touchscreen). The reset button was implemented to end the game at any time and end the main loop so that the motors would be inactive.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Although we got our project to the point where it worked well enough to show that we were able to create a working game, we definitely fell short of our goal of implementing a control system of not only stabilizing the ball, but also controlling its position and responding to disturbances. Listed below are our successes that greatly contributed to this project, as well as how they could be improved upon.&lt;br /&gt;
&lt;br /&gt;
*A robust mechanical design that allowed for more than adequate range of screen tilting, as well as good choices of equipment and materials for not only the job at hand, but also future implementations.&lt;br /&gt;
**The one shortcoming in this department is we should have had a higher threading ratio in that the linear motion of the screen should be greater per motor revolution in order to have a faster response.&lt;br /&gt;
*We were able to have proportional control between the position of the joystick and the speed of the motors.&lt;br /&gt;
**For automatic control we should have the tilting of the joystick proportional to the angle of the screen instead of the speed. We got this working to an extent before we scrapped the automatic contol. It is further explained below.&lt;br /&gt;
*We had a successful electric design that allowed for great flexibility within the software to do what we needed, while using a minimal amount of PIC inputs.&lt;br /&gt;
*The source code we wrote ended up being clean, well commented, and easy to modify and experiment with. The modular approach that we took with it will be helpful to future groups who will easily be able to glean portions of the code.&lt;br /&gt;
**Unfortunately the code had a couple bugs in it that were only able to be ironed out after the equipment was returned, including a poorly placed delay that caused a terrible refresh rate in the touchscreen and joystick response. These bugs caused a lot of gameplay issues, but although we have not been able to test the improved code, the changes we made were definitely harmless and would have greatly improved the gameplay.&lt;br /&gt;
*The game ended up being fun to play, and allowed for true interaction between man and machine. We were also able to successfully use the touchscreen, adding valuable information to the wiki about a previously unused technology.&lt;br /&gt;
**The responses of the game were clunky, the results of the game were somewhat unpredictable, and our coin slot didn&amp;#039;t work as seamlessly with the rest of the system as we would have liked.&lt;br /&gt;
&lt;br /&gt;
===Future Action===&lt;br /&gt;
&lt;br /&gt;
The main thing that would have been improved in our project if we had more time is the PIC control of the touchscreen. We put a great deal of effort into getting it working, but we simply ran out of time and had to scrap that idea not long before the project was due. Mechanically, we needed to have a better threading ratio on the bolts, and a more powerful motor would probably help as well. The rest of the work would be done on paper and in software.&lt;br /&gt;
&lt;br /&gt;
On paper, the first thing we would need to figure out a PD control system to control this ball. This would consist of an equation that relates the tilting angle necessary to counteract proportionally both the position of the ball on the touchscreen as well as the velocity of the ball. Counteracting the position of the ball would be very easy, and could simply be worked in software by telling the motors to tilt the screen so that it would roll towards the center, or whatever point we tell it to go to. Counteracting the velocy would be more tricky, as we would have to calculate the momentum of the ball, and then figure out the force necessary for counteracting the momentum. The screen would then have to be tilted so that the sine of the tilting angle times the gravitational constant would equal the necessary stopping force. We drafted some code for finding the velocity of the ball:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   //Measure velocity readings for motor encoder&lt;br /&gt;
   if (xcount&amp;gt;40 &amp;amp;&amp;amp; ycount&amp;gt;40) {         &lt;br /&gt;
      xold=xnew;&lt;br /&gt;
      xnew = (xmeasure/xcount);&lt;br /&gt;
      yold=ynew;         &lt;br /&gt;
      ynew = (ymeasure/ycount);&lt;br /&gt;
      xvelocity = (xnew-xold);&lt;br /&gt;
      yvelocity = (ynew-yold);&lt;br /&gt;
      xcount=0;&lt;br /&gt;
      ycount=0;&lt;br /&gt;
      xmeasure=0;&lt;br /&gt;
      ymeasure=0;&lt;br /&gt;
      }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code averages good values (not misreadings) of each axis readings and then subtracts the from the old average to get a number that corresponds to a velocity. The main problem with this is that the occurence of misreadings was generally very high because of the small contact point between the steel ball and the screen.&lt;br /&gt;
&lt;br /&gt;
We also drafted some code to read the encoders and tilt the screen to the correct angle:&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8556</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8556"/>
		<updated>2008-03-21T05:56:01Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|200px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two potentiometers) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Motorandconnection.JPG|right|thumb|Faulhaber Motor with epoxy connection to metal frame|200px]]&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two Falhauber motors mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame).  By controlling the speed of the motors via pulse width modulation, the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
This project was programmed using [[CCS C]] on a PIC 18F4520. See the page on [[4520 Board use]] for more information on using the boards we used.&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8553</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8553"/>
		<updated>2008-03-21T05:49:30Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|thumb|200px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two potentiometers) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two Falhauber motors mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame).  By controlling the speed of the motors via pulse width modulation, the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8551</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8551"/>
		<updated>2008-03-21T05:48:30Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|thumb|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two potentiometers) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two Falhauber motors mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame).  By controlling the speed of the motors via pulse width modulation, the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8550</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8550"/>
		<updated>2008-03-21T05:48:15Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|thumb|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two potentiometers) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two Falhauber motors mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame).  By controlling the speed of the motors via pulse width modulation, the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found [http://hades.mech.northwestern.edu/wiki/index.php/Resistive_Touchscreen here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=8548</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=8548"/>
		<updated>2008-03-21T05:46:24Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;[[ME 333 end of course schedule]]&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&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. [http://depot.northwestern.edu/mht363/public_html/IR%20Track/Mar%2019%20IR%20tracker.mp4 See Spot Run.]&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;
&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;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
[[image:T14-project-action-08.jpg|thumb|200px|right]]&lt;br /&gt;
&lt;br /&gt;
This is a tilting touchsreen that allows the user to control a rolling ball. The feedback from the touchscreen allows the user to play the game of trying to keep the ball in the center of the screen. The game is set-up in an arcade-type fashion in which there is no way to win, only lose, and the machine will simply keep eating your money.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;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_setup1.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;
&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>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8542</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8542"/>
		<updated>2008-03-21T05:32:29Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Based off an original idea of ball juggling, the purpose of our project was to test and gauge the capability of using a [http://www.bergquistcompany.com/touchscreens.cfm resistive touchscreen] with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that would keep a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we would design a control system that would use a two-axis actuator system to move the touchscreen up and down depending on disturbances to keep the metal ball in the same place. Automatic control and manual control elements were to be implemented with the manual control element.&lt;br /&gt;
&lt;br /&gt;
However, due to complications with our touchscreen readings, our group decided to focus on the essentials of our project and have it focus on both the touchscreen capabilities and try to make the project as interactive as possible. A joystick (made from two potentiometers) was used to control the two motors which would lift the table up in either axis. The game begins with a coin machine which, when a coin is slided in, would set off a contact and initiate the motor control. The design of our game was so that the player would attempt to keep the ball in a restricted region in the middle of the touchscreen, which was marked in black. The outside region of the touchscreen, marked in red, would set off LED&amp;#039;s that would go off if the player stayed in the red region for an extended time. The player would lose after 4 LED&amp;#039;s light up and the buzzer goes off. The player can reset the game but the motor control would cease to function and a coin is needed to reactivate the game again.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
Our team weighed several alternatives for a mechanical system that could turn the screen in two axes.  Potential solutions included a gimble system with a double-frame design and a pully-operated system that would lift up on two sides of the screen.  Eventually, we decided on a system that was theoretically less precise, but much simpler and requiring less power (since one motor does not need to lift another).  The system worked well under joystick control, but is only reliable for small tilting angles.&lt;br /&gt;
&lt;br /&gt;
A sheet metal frame was built around the frame for protection, supported at its center of gravity by a pillar attached to the wooden base.  The frame can freely tilt in two directions, allowing all possible ball movements.  By raising and lowering two adjacent sides of the frame, the touch screen can be tilted in two directions.  This motion is provided by two Falhauber motors mounted underneath the screen.  The output shaft of the motors&amp;#039; gear boxes are attached to a threaded rod by couplers that we machined for the purpose.  The couplers are attached to the motor shaft by a radial set screw and to the threaded rods by locking nuts.  Riding on these rods are two threaded aluminum pieces, which are attached to the bottom of the frame via flexible tubing and epoxy.  As the angle of the screen changes in one direction, the location of the attachment of the other motor moves slightly relative to the base of the motor.  The flexible coupling allows for this motion, while providing vertical stability and transferring the up and down motion of the threaded pieces to the sides of the frame.  Provided that the tilt angle remains small, its value can be approximated by the inverse tangent of the vertical motion of the threaded rod divided by 9cm (the horizontal distance from the tubing connection to the center of the frame).  By controlling the speed of the motors via pulse width modulation, the tilt angles of the touch screen can be changed at a variety of speeds.&lt;br /&gt;
&lt;br /&gt;
Other features include adjustable legs for stabilizing the wooden base on an uneven surface, and an upper frame above the touchscreen that prevents the ball from rolling onto the non-sensing regions at the periphery of the touchscreen.  The mechanical design for this project was the simplest and most inexpensive option for this application; if a greater level of precision were required, a more complicated mechanism may have been necessary.&lt;br /&gt;
&lt;br /&gt;
The coin slot box was simply a ramp that would lead the dropped coin onto a conducting plate. The plate was supported by a weak spring that would bend under the weight of the coin to briefly touch another conducting plate below it before the coin rolled off. The brief contact between the two plates would send a high voltage to the PIC microcontroller.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
Information about the specifics, implementation and code that was used for the reading of the resistive touchscreen can be found here. [[Resistive Touchscreen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Resistive_Touchscreen&amp;diff=8453</id>
		<title>Resistive Touchscreen</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Resistive_Touchscreen&amp;diff=8453"/>
		<updated>2008-03-21T02:08:58Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[image:Bergquist hand ball balancing.jpg|[[A small Bergquist resistive touchscreen]]|right]]&lt;br /&gt;
&lt;br /&gt;
Resistive touchscreens are useful for measuring the position of an object on top of them, or as an interesting user interface feature.  The [http://www.bergquistcompany.com/touchscreens.cfm Bergquist] company sells them in a variety of sizes, ranging from 3.5 to 23 inches diagonal.  &lt;br /&gt;
&lt;br /&gt;
The 12.1 inch version was used in the [[Ball Balancing Challenge]] project.  Its [http://www.bergquistcompany.com/to_technical_specs.cfm specifications] can be found on the Bergquist website.  The screens are transparent and are meant to be installed over an LCD display; however, they are also useful in a horizontal orientation (as in the &amp;quot;Ball Balancing Challenge&amp;quot; project) for sensing the position of an object resting above.  &lt;br /&gt;
&lt;br /&gt;
According to the technical specifications, the activation force for this touch screen is 50g.  From experience, activation is more reliable with a heavier weight. The area of contact may also play a role in activation; metal balls rolling on the screen produced a slightly noisy signal which needed to be filtered for reliable use in a real-time system.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
&lt;br /&gt;
A resistive touchscreen is essentially a large variable resistor.  When a potential is put across two opposite sides of the touch screen, an output voltage can be read that is proportional to the touching distance between the activated sides.  The Bergqist screen is a 5-wire resistive screen; its connections consist of four wires going to each of the corners (upper left, upper right, lower left, lower right) and one that goes to the surface.  A potential across two opposite sides of the screen results in a gradient across the screen in that direction.  When the surface is pushed in at a certain point, it forms a circuit, the output voltage of which can be read as an analog input into a PIC chip.&lt;br /&gt;
&lt;br /&gt;
There are several ways to read a 5-wire resistive touchscreen.  In the &amp;quot;Ball Balancing Challenge&amp;quot; project, the voltage gradient in one direction was created by placing +5 volts on two adjacent corners (for example the upper right and upper left) and grounding the other two.  The position in the vertical direction was then read as proportional to the voltage on the middle (surface) wire.&lt;br /&gt;
&lt;br /&gt;
Of course, this method only allows for the reading of one axis of the screen at a time.  In order to read both the X and Y positions of the touchscreen, it is possible to use an interrupt service routine to switch rapidly between X and Y readings.  For example, the +5V side can be switched between X and Y positions by alternating the voltage between the upper left (UL) and upper right (UR) corners and the upper left and lower left (LL) corners.  Correspondingly, grounding will be switched between the lower left and lower right (LR) corners, and the upper right and lower right corners.  This results in a type of square wave output on the screen wire, with its voltage representing the vertical and horizontal positions alternatively.  &lt;br /&gt;
&lt;br /&gt;
The voltage gradient in both the X and Y directions is linearly distributed from +5V to ground.  Because the touch screens are typically rectangular, it may be necessary to multiply one of the readings by the screen&amp;#039;s aspect ratio in order to create an equal coordinate system.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
The voltage switching described above must be accomplished quickly and precisely (so as to avoid a shortage).  One way to accomplish this is to permanently power opposite corners with +5V and ground, and then switch the other two according to an ISR.  The alternating PIC output signal is sent to one of the corners, and the other one gets its opposite signal through an inverter.  The inverter ensures that only one axis of the touch screen is activated at a time.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Touchscreen-circuit-diagram.JPG|center|thumb|Touchscreen Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
This code will power the touchscreen and take readings of the x and y axes. It might be a good idea when reading this code to put the touchscreen reading into an interrupt service routine so the screen can be read regardless of what else is going on.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
touchscreen.c &lt;br /&gt;
Reads the touchscreen individually as two axes. &lt;br /&gt;
PIC powers either the Upper Left (Y-axis reading) or the Lower Right (X-axis reading) and grounds what it doesn&amp;#039;t power.&lt;br /&gt;
Output reading is the value on that axis.&lt;br /&gt;
Upper Left (UL) corner is PIN_C1, and Lower Left (LR) corner is always its inverse.&lt;br /&gt;
Upper Right (UR) corner is always high, and lower right (LL) is always ground, its inverse.&lt;br /&gt;
Peak voltage: Top reading voltage=4V and bottom reading voltage=1.2V&lt;br /&gt;
Reading is 0V when nothing is touching the screen.&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }               &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;
== References ==&lt;br /&gt;
&lt;br /&gt;
1. [http://en.wikipedia.org/wiki/Microphone Microphone - From Wikipedia, the free encyclopedia] &amp;lt;br&amp;gt;&lt;br /&gt;
2. [http://www.national.com/nationaledge/dec02/article.html Integrated Circuits for High Performance Electret Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
[http://www.bergquistcompany.com/to_flexibility.cfm Bergquist Resistive Touchscreen Reference] &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Resistive_Touchscreen&amp;diff=8448</id>
		<title>Resistive Touchscreen</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Resistive_Touchscreen&amp;diff=8448"/>
		<updated>2008-03-21T01:58:47Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
[[image:Bergquist hand ball balancing.jpg|[[A small Bergquist resistive touchscreen]]|right]]&lt;br /&gt;
&lt;br /&gt;
Resistive touchscreens are useful for measuring the position of an object on top of them, or as an interesting user interface feature.  The [http://www.bergquistcompany.com/touchscreens.cfm Bergquist] company sells them in a variety of sizes, ranging from 3.5 to 23 inches diagonal.  &lt;br /&gt;
&lt;br /&gt;
The 12.1 inch version was used in the [[Ball Balancing Challenge]] project.  Its [http://www.bergquistcompany.com/to_technical_specs.cfm specifications] can be found on the Bergquist website.  The screens are transparent and are meant to be installed over an LCD display; however, they are also useful in a horizontal orientation (as in the &amp;quot;Ball Balancing Challenge&amp;quot; project) for sensing the position of an object resting above.  &lt;br /&gt;
&lt;br /&gt;
According to the technical specifications, the activation force for this touch screen is 50g.  From experience, activation is more reliable with a heavier weight. The area of contact may also play a role in activation; metal balls rolling on the screen produced a slightly noisy signal which needed to be filtered for reliable use in a real-time system.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
&lt;br /&gt;
A resistive touchscreen is essentially a large variable resistor.  When a potential is put across two opposite sides of the touch screen, an output voltage can be read that is proportional to the touching distance between the activated sides.  The Bergqist screen is a 5-wire resistive screen; its connections consist of four wires going to each of the corners (upper left, upper right, lower left, lower right) and one that goes to the surface.  A potential across two opposite sides of the screen results in a gradient across the screen in that direction.  When the surface is pushed in at a certain point, it forms a circuit, the output voltage of which can be read as an analog input into a PIC chip.&lt;br /&gt;
&lt;br /&gt;
There are several ways to read a 5-wire resistive touchscreen.  In the &amp;quot;Ball Balancing Challenge&amp;quot; project, the voltage gradient in one direction was created by placing +5 volts on two adjacent corners (for example the upper right and upper left) and grounding the other two.  The position in the vertical direction was then read as proportional to the voltage on the middle (surface) wire.&lt;br /&gt;
&lt;br /&gt;
Of course, this method only allows for the reading of one axis of the screen at a time.  In order to read both the X and Y positions of the touchscreen, it is possible to use an interrupt service routine to switch rapidly between X and Y readings.  For example, the +5V side can be switched between X and Y positions by alternating the voltage between the upper left (UL) and upper right (UR) corners and the upper left and lower left (LL) corners.  Correspondingly, grounding will be switched between the lower left and lower right (LR) corners, and the upper right and lower right corners.  This results in a type of square wave output on the screen wire, with its voltage representing the vertical and horizontal positions alternatively.  &lt;br /&gt;
&lt;br /&gt;
The voltage gradient in both the X and Y directions is linearly distributed from +5V to ground.  Because the touch screens are typically rectangular, it may be necessary to multiply one of the readings by the screen&amp;#039;s aspect ratio in order to create an equal coordinate system.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
The voltage switching described above must be accomplished quickly and precisely (so as to avoid a shortage).  One way to accomplish this is to permanently power opposite corners with +5V and ground, and then switch the other two according to an ISR.  The alternating PIC output signal is sent to one of the corners, and the other one gets its opposite signal through an inverter.  The inverter ensures that only one axis of the touch screen is activated at a time.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Touchscreen-circuit-diagram.JPG|center|thumb|Touchscreen Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
1. [http://en.wikipedia.org/wiki/Microphone Microphone - From Wikipedia, the free encyclopedia] &amp;lt;br&amp;gt;&lt;br /&gt;
2. [http://www.national.com/nationaledge/dec02/article.html Integrated Circuits for High Performance Electret Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
[http://www.bergquistcompany.com/to_flexibility.cfm Bergquist Resistive Touchscreen Reference] &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Touchscreen-circuit-diagram.JPG&amp;diff=8446</id>
		<title>File:Touchscreen-circuit-diagram.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Touchscreen-circuit-diagram.JPG&amp;diff=8446"/>
		<updated>2008-03-21T01:58:24Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8436</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8436"/>
		<updated>2008-03-21T01:28:48Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Software Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
The purpose of our project was to test and gauge the ability of using a touchscreen with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that keeps a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we could use a two-axis actuator system to  to keep the ball stable. It will respond to disturbances to keep a metal ball in the same place.&lt;br /&gt;
&lt;br /&gt;
Our project is to use an infrared touch-screen to balance and move a ball in a controlled manner.  The ball will be balanced on top of the horizontally oriented screen and will be moved by tilting the screen in two axes.  &lt;br /&gt;
&lt;br /&gt;
To operate the device, a user would select a point on the screen (likely by touching it), and then would place a ball on the screen’s surface.  The ball’s position would be continually tracked by the touch screen’s infrared intersection array.  This information would be sent to a processor, which would control two motors and tilt the screen in order to move the ball to the selected location as quickly as possible. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The purpose of our project is to undertake the design and fabrication of a computer mouse that controls the on-computer cursor with hand movements in two dimensions -- roll and pitch (in the style of the WiiMote). We will accomplish this through the use of a two-axis accelerometer to determine the angle (x and y) of the remote relative to a preset (0, 0) and a XBee module for communication between the device and the computer. One of our primary goals will be to optimize the user’s experience by creating a device of reasonable size and weight, and focusing on an intuitive interface, in terms of cursor resolution and a tracking (cursor hold) button that is analogous to lifting a traditional mouse off a surface and relocating it.&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(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;
[[media:T14-source-code.c|See full code here]]&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:T14-source-code.c&amp;diff=8435</id>
		<title>File:T14-source-code.c</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:T14-source-code.c&amp;diff=8435"/>
		<updated>2008-03-21T01:28:11Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8434</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8434"/>
		<updated>2008-03-21T01:20:50Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
The purpose of our project was to test and gauge the ability of using a touchscreen with a PIC Microcontroller. Our original projected means for testing the touchscreen for our project was to attempt to design and implement a system that keeps a round metal ball in the center of the touchscreen. Using the touchscreen&amp;#039;s analog outputs of position, we could use a two-axis actuator system to  to keep the ball stable. It will respond to disturbances to keep a metal ball in the same place.&lt;br /&gt;
&lt;br /&gt;
Our project is to use an infrared touch-screen to balance and move a ball in a controlled manner.  The ball will be balanced on top of the horizontally oriented screen and will be moved by tilting the screen in two axes.  &lt;br /&gt;
&lt;br /&gt;
To operate the device, a user would select a point on the screen (likely by touching it), and then would place a ball on the screen’s surface.  The ball’s position would be continually tracked by the touch screen’s infrared intersection array.  This information would be sent to a processor, which would control two motors and tilt the screen in order to move the ball to the selected location as quickly as possible. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The purpose of our project is to undertake the design and fabrication of a computer mouse that controls the on-computer cursor with hand movements in two dimensions -- roll and pitch (in the style of the WiiMote). We will accomplish this through the use of a two-axis accelerometer to determine the angle (x and y) of the remote relative to a preset (0, 0) and a XBee module for communication between the device and the computer. One of our primary goals will be to optimize the user’s experience by creating a device of reasonable size and weight, and focusing on an intuitive interface, in terms of cursor resolution and a tracking (cursor hold) button that is analogous to lifting a traditional mouse off a surface and relocating it.&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electrical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. This went to one of the PIC&amp;#039;s analog inputs. The coin would simply fall on a simple switch, connecting 5V to the PIC. The touchscreen input looks like a square wave, except the two values being received correspond to the voltage from each axis. Separating these two values is done in software.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the motors corresponds directly to the joystick input. The PIC output goes both to the H-bridge and an inverter for each motor, so that the motor sees not a PWM signal and ground, but a PWM signal with its inverse PWM signal. As a result of this, both poles of the motor see the same thing when the high and low pulses of the signal are equal. The motors turn one way proportionally to the joystick position when the PWM has more time high than low (when that joystick potentiometer is sending a higher signal)and the other way when the PWM is more low than high.&lt;br /&gt;
&lt;br /&gt;
The PIC output to the touchscreen is very simple. Although we had it go through an H-bridge to amplify the current, this is probably not necessary. Because the diagonally opposite corners of the touchscreen always have an opposite voltage going into them, we just ran the signal through an inverter so that we could control all four corners with only two PIC outputs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8427</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8427"/>
		<updated>2008-03-21T00:38:56Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Software Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8426</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8426"/>
		<updated>2008-03-21T00:37:08Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Software Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
The opening lines are necessary for establishing that we are using a PIC 18F4520, analog inputs, a clock, connecting with an ICD, and that we are using pin 36 instead of 16 for the second PWM output. This is also where we establish all of our variables and functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The main function starts with setting the correct initial values to the variables, and setting up the timers and analog ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
   //Flash 3 times to let us know we&amp;#039;re running&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following portion of code shows what happens when the game is continuously played. First the game waits for a coin, then it plays the game until the user strikes out, then it stops the motors from spinning and again waits for a coin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The touchscreen is read by having the PIC send alternating signals to 2 of the corners that are diagonal to each other while keeping the other two signals constant. This allows the touchscreen to read both axes each run through, and then display them in a manner where the x-axis reading corresponds to PIC LED outputs D0-D3, and the y-axis reading corresponds to outputs D4-D7. Although this gives visually a very poor resolution on the reading, it serves well enough as a debugging tool to make sure the reading is working. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Touchscreen reading, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find the &amp;quot;winning&amp;quot; ranges of the black area on the touchscreen, we measured the voltage output on each axis on each boundary line, and converted it from the 0V to 5V scale to the quantized 8 bit (0 to 255) scale. Our code then checks to see if the ball is not in this zone before assigning a strike to the user. The counter variable is to ensure that the ball is outside the range enough times  in a row, and a low reading is not simply the result of inconsistencies in the touchscreen reading.&lt;br /&gt;
To stop the machine from simply running up the strikes while the ball is in the red, the code ensures that a &amp;quot;strike&amp;quot; cannot be assigned until a &amp;quot;ball&amp;quot; is assigned before hand.&lt;br /&gt;
&lt;br /&gt;
For each strike, a corresponding LED is lit up, and upon the last strike, the buzz function is set off.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
The PIC reads the joystick and quantizes the input from the analog 0V to 5V to the 8 bit quantized 0 to 255. It then scales that number to be between 0 and 78, the PWM extremes.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The buzz() function resets the counting variables to zero and sets the buzzer off by oscillating a PIC output into a basic buzzer speaker at an audible frequency.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter = 0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
   output_low(PIN_E0);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8423</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8423"/>
		<updated>2008-03-21T00:11:15Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Software Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
Source Code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
touchscreen.c Mechatronics 333 Team 14 2/22/08&lt;br /&gt;
Reads the touchscreen individually as two axes. Actuates motor based on either touchscreen or joystick control.&lt;br /&gt;
PIC powers either the Upper Left (Y-axis reading) or the Lower Right (X-axis reading) and grounds what it doesn&amp;#039;t power.&lt;br /&gt;
Output reading is the value on that axis.&lt;br /&gt;
Two channels of PWM output, with the PWM2 output moved from pin 16 to pin 36 to avoid conflict with Timer1 input&lt;br /&gt;
Upper Left (UL) corner is PIN_C1, and Lower Left (LR) corner is always its inverse.&lt;br /&gt;
Upper Right (UR) corner is always high, and lower right (LL) is always ground, its inverse.&lt;br /&gt;
Peak voltage: Top reading voltage=4V and bottom reading voltage=1.2V&lt;br /&gt;
Min xread,yread values: 62,70&lt;br /&gt;
Max xread,yread values: 189,177&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#DEVICE ADC=8                      // set ADC to 8 bit accuracy&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT, CCP2B3      // CCP2B3 moves PWM2 output to pin 36 (RB3) rather than pin 16 (RC1)&lt;br /&gt;
#device icd=true&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int yread,xread,m,j=0;&lt;br /&gt;
int read1pwm,read2pwm=0;&lt;br /&gt;
int read1,read2=0;&lt;br /&gt;
int coin,strike,ball=0;&lt;br /&gt;
signed int16 counter=0;&lt;br /&gt;
&lt;br /&gt;
void buzz();&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   for (j=0;j&amp;lt;3;j++){&lt;br /&gt;
      output_d(0b11111111);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
      output_d(0);&lt;br /&gt;
      delay_ms(250);&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   counter=0;&lt;br /&gt;
  &lt;br /&gt;
   output_high(PIN_C1);          //Start with UL high, LR low ***THESE WILL CHANGE***&lt;br /&gt;
   output_high(PIN_C0);          //This is the pin for UR. It will be run through an inverter for LL&lt;br /&gt;
                                 //the bottom left corner. ***THESE ARE PERMANENT***&lt;br /&gt;
  &lt;br /&gt;
   setup_adc_ports(AN0_TO_AN2);        // Enable analog inputs; choices run from just AN0, up to AN0_TO_AN11&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      // the range selected has to start with AN0&lt;br /&gt;
  &lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 77, 16);        // clock at 16KHz, interrupt every 4*50nS * 4 * (155+1) * 16 = 2.00mS&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(GLOBAL);  &lt;br /&gt;
 &lt;br /&gt;
   setup_ccp1(CCP_PWM);       // PWM output on CCP1/RC2, pin 17   this goes to y-axis motor&lt;br /&gt;
   setup_ccp2(CCP_PWM);       // PWM output on CCP2/RB3, pin 36   this goes to x-axis motor&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(39);&lt;br /&gt;
   set_pwm2_duty(39);&lt;br /&gt;
  &lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
  &lt;br /&gt;
      set_pwm1_duty(39);&lt;br /&gt;
      set_pwm2_duty(39);&lt;br /&gt;
     &lt;br /&gt;
      //Wait for coin to be inserted&lt;br /&gt;
      while (coin==0) {                &lt;br /&gt;
         if (input(PIN_E1)) coin=1;&lt;br /&gt;
         else delay_ms(100);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      //Gameplay begins. Controls go dead when strikes go too high; &lt;br /&gt;
      while (coin==1) {&lt;br /&gt;
         //TOUCHSCREEN READing, looks at the touchscreen readings&lt;br /&gt;
         if (m==0) {&lt;br /&gt;
            output_high(PIN_C1);       //UL goes high, thus LR goes low; y-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            yread = read_adc();       //Read y axis           &lt;br /&gt;
            m++;&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_low(PIN_C1);        //UL goes low, thus LR goes high; x-axis can be read&lt;br /&gt;
            set_adc_channel(0);&lt;br /&gt;
            delay_us(10);          &lt;br /&gt;
            xread = read_adc();       //Read x axis&lt;br /&gt;
            m=0;&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         //Check to see if the Ball is outide the allowed range of values to be &amp;quot;in the black&amp;quot; of the touchscreen&lt;br /&gt;
         if ((yread&amp;lt; 90) | (yread &amp;gt;150) | (xread &amp;lt;90) | (xread &amp;gt; 150)) {&lt;br /&gt;
            counter++;&lt;br /&gt;
            if ((counter==3) &amp;amp;&amp;amp; (strike==ball)) {&lt;br /&gt;
               strike++;         //If ball is &amp;quot;in the red&amp;quot; for a sufficiently long time, a strike is added.&lt;br /&gt;
            }&lt;br /&gt;
         }       &lt;br /&gt;
         else {&lt;br /&gt;
            counter--;&lt;br /&gt;
            //Check to see if the ball has returned from being &amp;quot;in the red.&amp;quot;&lt;br /&gt;
            if ((counter==-1)  &amp;amp;&amp;amp; (strike&amp;gt;ball)) {&lt;br /&gt;
               ball++;&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
         if ((counter==3) | (counter == -2)) counter=0;&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
         if (strike==2) {&lt;br /&gt;
            output_high(PIN_A3);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==3) {&lt;br /&gt;
            output_high(PIN_A4);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==4) {&lt;br /&gt;
            output_high(PIN_A5);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==5) {&lt;br /&gt;
            output_high(PIN_E2);&lt;br /&gt;
         }&lt;br /&gt;
         if (strike==6) {&lt;br /&gt;
            output_high(PIN_E0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            buzz();&lt;br /&gt;
         }&lt;br /&gt;
        &lt;br /&gt;
 &lt;br /&gt;
        &lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
         //Joystick Control&lt;br /&gt;
         if (input(PIN_C7) != 0) {  // toggle switch that switches between Joystick control system and Touchscreen control system&lt;br /&gt;
            set_adc_channel(2);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN1&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read1 = read_adc();                       //x-axis&lt;br /&gt;
            if (read1&amp;lt;145 &amp;amp;&amp;amp; read1&amp;gt;115) read1pwm=39;&lt;br /&gt;
            else read1pwm=(read1*.3);&lt;br /&gt;
            set_pwm1_duty(read1pwm);&lt;br /&gt;
           &lt;br /&gt;
            set_adc_channel(1);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN2&lt;br /&gt;
            delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
            read2 = read_adc();                      //y-axis&lt;br /&gt;
            if (read2&amp;lt;145 &amp;amp;&amp;amp; read2&amp;gt;115) read2pwm=39;&lt;br /&gt;
            else read2pwm=(read2*.3);&lt;br /&gt;
            set_pwm2_duty(read2pwm);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            output_d(0);&lt;br /&gt;
            set_pwm1_duty(39);&lt;br /&gt;
            set_pwm2_duty(39);&lt;br /&gt;
            }&lt;br /&gt;
        &lt;br /&gt;
         //LED readings for XY locations of the touchscreen&lt;br /&gt;
         if (xread&amp;lt;75) {                &lt;br /&gt;
            output_low(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_low(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_low(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else if (xread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_low(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D0);     &lt;br /&gt;
            output_high(PIN_D1);&lt;br /&gt;
            output_high(PIN_D2);&lt;br /&gt;
            output_high(PIN_D3);&lt;br /&gt;
         }&lt;br /&gt;
         if (yread&amp;lt;75) {&lt;br /&gt;
            output_low(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;110) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_low(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;145) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_low(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else if (yread&amp;lt;180) {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_low(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
         else  {&lt;br /&gt;
            output_high(PIN_D4);     &lt;br /&gt;
            output_high(PIN_D5);&lt;br /&gt;
            output_high(PIN_D6);&lt;br /&gt;
            output_high(PIN_D7);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void buzz() {&lt;br /&gt;
&lt;br /&gt;
   coin=0;&lt;br /&gt;
   strike=0;&lt;br /&gt;
   ball=0;&lt;br /&gt;
   output_low(PIN_A3);&lt;br /&gt;
   output_low(PIN_A4);  &lt;br /&gt;
   output_low(PIN_A5);&lt;br /&gt;
   output_low(PIN_E2);&lt;br /&gt;
   output_low(PIN_E0);&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
   while (input(PIN_C6)==0) {&lt;br /&gt;
      output_high(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
      output_low(PIN_C4);&lt;br /&gt;
      delay_us(100);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8422</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8422"/>
		<updated>2008-03-21T00:10:22Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8417</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8417"/>
		<updated>2008-03-20T23:57:56Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-electronics-photo-closeup.JPG|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:T14-electronics-photo-closeup.JPG&amp;diff=8412</id>
		<title>File:T14-electronics-photo-closeup.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:T14-electronics-photo-closeup.JPG&amp;diff=8412"/>
		<updated>2008-03-20T23:55:03Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8397</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8397"/>
		<updated>2008-03-20T23:28:30Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
===Theory===&lt;br /&gt;
&lt;br /&gt;
Through his [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm research], Professor Lynch found that when a pivot point is placed under a platform that is attached to speakers, sinks and nodes can be created by places speaker vibrations at different amplitudes and phases.  Applying his research to our project, it was determined that if we placed two speakers at equal amplitudes and opposite phases, a sink would be created in between the speakers.  This result can be thought of as the center being the center of a teeter-totter, in which two people of equal mass but at completely opposite phases would cause the teeter-totter to rotate perfectly around the center pivot point.  However, if the two speakers were at equal amplitudes and perfectly in phase with each other, that side of the plate would move up and down in one motion, causing the sink to be at the other side of the plate.&lt;br /&gt;
&lt;br /&gt;
We found that if we alternated between two different phases that created two orthogonal sinks, we could create a node at the intersection.  For example, if we wanted to create a node at 12 o&amp;#039;clock, we would alternate between the radial and orthogonal phases.  In the radial phase, we created a sink along the diameter of the plate between the two speakers that were not at 12 o&amp;#039;clock, namely speakers B and C.  Using the theory of creating sinks, we placed speakers B and C at equal amplitude and 180 degrees out of phase with each other.  If several small objects were placed on the plate at this point, all the objects would converge to the central line of the plate.  Next, in order to create the orthogonal sink that would create a node at 12 o&amp;#039;clock, we placed speakers B and C in phase and at equal amplitude.  However, in order to counteract the forces from speakers B and C, we put speaker A (the speaker at 12 o&amp;#039;clock) at a weak amplitude and 180 degrees out of phase with speakers B and C in the orthogonal phase.&lt;br /&gt;
&lt;br /&gt;
This same notion was the used to create all of the even number nodes on the clock face.  In order to create the nodes at the odd numbers, we slightly changed the amplitudes of the speakers at the previous time until the correct placement was found.&lt;br /&gt;
&lt;br /&gt;
Although theoretically our design should have allowed us to program the clock using symmetry, due to slight imperfections in the design and in the electrical components, we had to use some trial and error methods to place the nodes correctly.  Nonetheless, the theory allowed us to create nodes almost exactly where we wanted them to be.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
The Electical Design was fairly simple for this project. The inputs to the PIC were the joystick, coin slot, and the touchscreen. The outputs were the motors and the LED &amp;quot;strike&amp;quot; array. The touchscreen was also an output as it was controlled by the PIC.&lt;br /&gt;
&lt;br /&gt;
The user would control the joystick that was simply two potentiometers that would output a value between 0V and 5V, corresponding to both the x-axis and the y-axis. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Circuit_Photo_Team22.jpg|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;BER237-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8370</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8370"/>
		<updated>2008-03-20T22:44:18Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
===Theory===&lt;br /&gt;
&lt;br /&gt;
Through his [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm research], Professor Lynch found that when a pivot point is placed under a platform that is attached to speakers, sinks and nodes can be created by places speaker vibrations at different amplitudes and phases.  Applying his research to our project, it was determined that if we placed two speakers at equal amplitudes and opposite phases, a sink would be created in between the speakers.  This result can be thought of as the center being the center of a teeter-totter, in which two people of equal mass but at completely opposite phases would cause the teeter-totter to rotate perfectly around the center pivot point.  However, if the two speakers were at equal amplitudes and perfectly in phase with each other, that side of the plate would move up and down in one motion, causing the sink to be at the other side of the plate.&lt;br /&gt;
&lt;br /&gt;
We found that if we alternated between two different phases that created two orthogonal sinks, we could create a node at the intersection.  For example, if we wanted to create a node at 12 o&amp;#039;clock, we would alternate between the radial and orthogonal phases.  In the radial phase, we created a sink along the diameter of the plate between the two speakers that were not at 12 o&amp;#039;clock, namely speakers B and C.  Using the theory of creating sinks, we placed speakers B and C at equal amplitude and 180 degrees out of phase with each other.  If several small objects were placed on the plate at this point, all the objects would converge to the central line of the plate.  Next, in order to create the orthogonal sink that would create a node at 12 o&amp;#039;clock, we placed speakers B and C in phase and at equal amplitude.  However, in order to counteract the forces from speakers B and C, we put speaker A (the speaker at 12 o&amp;#039;clock) at a weak amplitude and 180 degrees out of phase with speakers B and C in the orthogonal phase.&lt;br /&gt;
&lt;br /&gt;
This same notion was the used to create all of the even number nodes on the clock face.  In order to create the nodes at the odd numbers, we slightly changed the amplitudes of the speakers at the previous time until the correct placement was found.&lt;br /&gt;
&lt;br /&gt;
Although theoretically our design should have allowed us to program the clock using symmetry, due to slight imperfections in the design and in the electrical components, we had to use some trial and error methods to place the nodes correctly.  Nonetheless, the theory allowed us to create nodes almost exactly where we wanted them to be.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Circuit_Photo_Team22.jpg|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Touchscreen&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;61-EMV15012VWK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;http://www.bergquistcompany.com Bergquist&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$62.00&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Joystick&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LA160&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:T14-schematic 1.JPG|center|thumb|Ball Balancing Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:T14-schematic_1.JPG&amp;diff=8363</id>
		<title>File:T14-schematic 1.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:T14-schematic_1.JPG&amp;diff=8363"/>
		<updated>2008-03-20T22:31:58Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8301</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8301"/>
		<updated>2008-03-20T20:53:16Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:T14-project-action-08.jpg|400px|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
===Theory===&lt;br /&gt;
&lt;br /&gt;
Through his [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm research], Professor Lynch found that when a pivot point is placed under a platform that is attached to speakers, sinks and nodes can be created by places speaker vibrations at different amplitudes and phases.  Applying his research to our project, it was determined that if we placed two speakers at equal amplitudes and opposite phases, a sink would be created in between the speakers.  This result can be thought of as the center being the center of a teeter-totter, in which two people of equal mass but at completely opposite phases would cause the teeter-totter to rotate perfectly around the center pivot point.  However, if the two speakers were at equal amplitudes and perfectly in phase with each other, that side of the plate would move up and down in one motion, causing the sink to be at the other side of the plate.&lt;br /&gt;
&lt;br /&gt;
We found that if we alternated between two different phases that created two orthogonal sinks, we could create a node at the intersection.  For example, if we wanted to create a node at 12 o&amp;#039;clock, we would alternate between the radial and orthogonal phases.  In the radial phase, we created a sink along the diameter of the plate between the two speakers that were not at 12 o&amp;#039;clock, namely speakers B and C.  Using the theory of creating sinks, we placed speakers B and C at equal amplitude and 180 degrees out of phase with each other.  If several small objects were placed on the plate at this point, all the objects would converge to the central line of the plate.  Next, in order to create the orthogonal sink that would create a node at 12 o&amp;#039;clock, we placed speakers B and C in phase and at equal amplitude.  However, in order to counteract the forces from speakers B and C, we put speaker A (the speaker at 12 o&amp;#039;clock) at a weak amplitude and 180 degrees out of phase with speakers B and C in the orthogonal phase.&lt;br /&gt;
&lt;br /&gt;
This same notion was the used to create all of the even number nodes on the clock face.  In order to create the nodes at the odd numbers, we slightly changed the amplitudes of the speakers at the previous time until the correct placement was found.&lt;br /&gt;
&lt;br /&gt;
Although theoretically our design should have allowed us to program the clock using symmetry, due to slight imperfections in the design and in the electrical components, we had to use some trial and error methods to place the nodes correctly.  Nonetheless, the theory allowed us to create nodes almost exactly where we wanted them to be.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Circuit_Photo_Team22.jpg|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Quadruple Half-H Drivers&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L293D &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$1.93&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Hex Inverter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;SN74HC04&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$0.47&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Emtel EMV15012V Wiring Kit&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;61-EMV15012VWK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Legacy Series II 4-channel, 300W Power Amplifier&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LA160&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Keystone Electronics Snap-Fit 90 PC Phono Jack&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;901K-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;3&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$3.81&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Radioshack 6-Ft. Shielded Cable, RCA Plug to RCA Plug&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;42-2367&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;3&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.radioshack.com Radioshack]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$14.97&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;20-ft Monster Cable 16-Gauge Speaker Wire&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S16-2XLN&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.radioshack.com Radioshack]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$9.97&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:team22_circuit.jpg|center|frame|Vibratory Clock Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:T14-project-action-08.jpg&amp;diff=8229</id>
		<title>File:T14-project-action-08.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:T14-project-action-08.jpg&amp;diff=8229"/>
		<updated>2008-03-20T19:01:33Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: A close-up picture of our project in action. Team 14, Mechatronics Winter 2008&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A close-up picture of our project in action. Team 14, Mechatronics Winter 2008&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8225</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8225"/>
		<updated>2008-03-20T18:52:25Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;NOTE: THIS PAGE CURRENTLY PERTAINS TO A DIFFERENT TEAM&amp;#039;S PROJECT, BUT IT WILL BE REPLACED VERY SOON WITH INFORMATION ABOUT THE LEGENDARY TEAM 14. STAY TUNED.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;B&amp;gt;THIEVES!!!  You first take our PIC, now our Wiki.  It&amp;#039;s on now!&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:T14-project-group-08.jpg|right|Left to right: JJ Darling, Alex Leung, Ben Schriesheim|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*JJ Darling - Electrical Engineering Class of 2009&lt;br /&gt;
*Ben Schriesheim - Manufacturing Engineering Class of 2008&lt;br /&gt;
*Alex Leung - Biomedical Engineering Graduate Student&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
===Theory===&lt;br /&gt;
&lt;br /&gt;
Through his [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm research], Professor Lynch found that when a pivot point is placed under a platform that is attached to speakers, sinks and nodes can be created by places speaker vibrations at different amplitudes and phases.  Applying his research to our project, it was determined that if we placed two speakers at equal amplitudes and opposite phases, a sink would be created in between the speakers.  This result can be thought of as the center being the center of a teeter-totter, in which two people of equal mass but at completely opposite phases would cause the teeter-totter to rotate perfectly around the center pivot point.  However, if the two speakers were at equal amplitudes and perfectly in phase with each other, that side of the plate would move up and down in one motion, causing the sink to be at the other side of the plate.&lt;br /&gt;
&lt;br /&gt;
We found that if we alternated between two different phases that created two orthogonal sinks, we could create a node at the intersection.  For example, if we wanted to create a node at 12 o&amp;#039;clock, we would alternate between the radial and orthogonal phases.  In the radial phase, we created a sink along the diameter of the plate between the two speakers that were not at 12 o&amp;#039;clock, namely speakers B and C.  Using the theory of creating sinks, we placed speakers B and C at equal amplitude and 180 degrees out of phase with each other.  If several small objects were placed on the plate at this point, all the objects would converge to the central line of the plate.  Next, in order to create the orthogonal sink that would create a node at 12 o&amp;#039;clock, we placed speakers B and C in phase and at equal amplitude.  However, in order to counteract the forces from speakers B and C, we put speaker A (the speaker at 12 o&amp;#039;clock) at a weak amplitude and 180 degrees out of phase with speakers B and C in the orthogonal phase.&lt;br /&gt;
&lt;br /&gt;
This same notion was the used to create all of the even number nodes on the clock face.  In order to create the nodes at the odd numbers, we slightly changed the amplitudes of the speakers at the previous time until the correct placement was found.&lt;br /&gt;
&lt;br /&gt;
Although theoretically our design should have allowed us to program the clock using symmetry, due to slight imperfections in the design and in the electrical components, we had to use some trial and error methods to place the nodes correctly.  Nonetheless, the theory allowed us to create nodes almost exactly where we wanted them to be.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Circuit_Photo_Team22.jpg|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Maxim Quad, 2-Wire Serial 8-Bit Digital-to-Analog Converter (U2)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;MAX520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$9.28&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Emtel 150W, 12V Power Supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;EMV15012V&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Emtel EMV15012V Wiring Kit&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;61-EMV15012VWK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Legacy Series II 4-channel, 300W Power Amplifier&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LA160&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Keystone Electronics Snap-Fit 90 PC Phono Jack&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;901K-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;3&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$3.81&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Radioshack 6-Ft. Shielded Cable, RCA Plug to RCA Plug&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;42-2367&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;3&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.radioshack.com Radioshack]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$14.97&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;20-ft Monster Cable 16-Gauge Speaker Wire&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S16-2XLN&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.radioshack.com Radioshack]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$9.97&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:team22_circuit.jpg|center|frame|Vibratory Clock Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:T14-project-group-08.jpg&amp;diff=8223</id>
		<title>File:T14-project-group-08.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:T14-project-group-08.jpg&amp;diff=8223"/>
		<updated>2008-03-20T18:50:41Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: Team Photo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Team Photo&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8065</id>
		<title>Ball Balancing Challenge</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Ball_Balancing_Challenge&amp;diff=8065"/>
		<updated>2008-03-20T07:42:10Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;NOTE: THIS PAGE CURRENTLY PERTAINS TO A DIFFERENT TEAM&amp;#039;S PROJECT, BUT IT WILL BE REPLACED VERY SOON WITH INFORMATION ABOUT THE LEGENDARY TEAM 14. STAY TUNED.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
[[Image:team22.jpg|right|Left to right: Brian Lesperance, Jennifer Breger, Daniel Pinkawa|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
*Jennifer Breger - Mechanical Engineering Class of 2009&lt;br /&gt;
*Brian Lesperance - Electrical Engineering Class of 2008&lt;br /&gt;
*Daniel Pinkawa - Mechanical Engineering Class of 2008&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
We built a horizontal circular platform that is actuated from underneath by three speakers placed in an equilateral triangle. The vibration of the platform causes a small object (e.g., an IC socket or a coin) to act as an hour &amp;quot;hand&amp;quot; on top of the platform.  The object slides around the circular platform, impelled by friction forces due to the vibration.  By placing the speakers at different phases and amplitudes, we got the objects to move to desired positions.  Due to the nodes created by the speaker vibrations, the object will move back to the correct hour if it is moved away.  Our project was given to us by Professor Colgate and was based upon the research of Professor Lynch.&lt;br /&gt;
&lt;br /&gt;
===Theory===&lt;br /&gt;
&lt;br /&gt;
Through his [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm research], Professor Lynch found that when a pivot point is placed under a platform that is attached to speakers, sinks and nodes can be created by places speaker vibrations at different amplitudes and phases.  Applying his research to our project, it was determined that if we placed two speakers at equal amplitudes and opposite phases, a sink would be created in between the speakers.  This result can be thought of as the center being the center of a teeter-totter, in which two people of equal mass but at completely opposite phases would cause the teeter-totter to rotate perfectly around the center pivot point.  However, if the two speakers were at equal amplitudes and perfectly in phase with each other, that side of the plate would move up and down in one motion, causing the sink to be at the other side of the plate.&lt;br /&gt;
&lt;br /&gt;
We found that if we alternated between two different phases that created two orthogonal sinks, we could create a node at the intersection.  For example, if we wanted to create a node at 12 o&amp;#039;clock, we would alternate between the radial and orthogonal phases.  In the radial phase, we created a sink along the diameter of the plate between the two speakers that were not at 12 o&amp;#039;clock, namely speakers B and C.  Using the theory of creating sinks, we placed speakers B and C at equal amplitude and 180 degrees out of phase with each other.  If several small objects were placed on the plate at this point, all the objects would converge to the central line of the plate.  Next, in order to create the orthogonal sink that would create a node at 12 o&amp;#039;clock, we placed speakers B and C in phase and at equal amplitude.  However, in order to counteract the forces from speakers B and C, we put speaker A (the speaker at 12 o&amp;#039;clock) at a weak amplitude and 180 degrees out of phase with speakers B and C in the orthogonal phase.&lt;br /&gt;
&lt;br /&gt;
This same notion was the used to create all of the even number nodes on the clock face.  In order to create the nodes at the odd numbers, we slightly changed the amplitudes of the speakers at the previous time until the correct placement was found.&lt;br /&gt;
&lt;br /&gt;
Although theoretically our design should have allowed us to program the clock using symmetry, due to slight imperfections in the design and in the electrical components, we had to use some trial and error methods to place the nodes correctly.  Nonetheless, the theory allowed us to create nodes almost exactly where we wanted them to be.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
&lt;br /&gt;
The Vibratory clock consists of a wooden base, held up by adjustable legs, three speakers, and a circular platform.  The following material were used to create the design:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Base:&amp;#039;&amp;#039;&lt;br /&gt;
*wood: 16&amp;quot; diameter, 0.75&amp;quot; thick&lt;br /&gt;
*holes: 6&amp;quot; diameter (3 total)&lt;br /&gt;
*adjustable legs: 3 rods: 3/8&amp;quot;-16; 4&amp;quot; long; 6 nuts total&lt;br /&gt;
&lt;br /&gt;
[[Image:speaker_supports.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Speakers:&amp;#039;&amp;#039;&lt;br /&gt;
*3 Pyramid Power PW677X: 300W, 4 Ohms, 6.5&amp;quot; Chrome Subwoofer&lt;br /&gt;
**previously adapted speakers replaced center of speaker with attachments 3&amp;quot; in height and 1/2&amp;quot; hole on top&lt;br /&gt;
**1/2&amp;quot; diameter PVC used to attach previous attachment to platform with a screw&lt;br /&gt;
***held in place by 2 set screws each&lt;br /&gt;
**centers placed 7.125&amp;quot; apart&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Circular Platform&amp;#039;&amp;#039;&lt;br /&gt;
*PVC/Acrylic: 11.75&amp;quot; diameter, 0.25&amp;quot; thick &lt;br /&gt;
**machined on the LaserJet&lt;br /&gt;
**screw holes counter-sunk at 7.125&amp;quot; apart&lt;br /&gt;
*2.875&amp;quot; above wooden base&lt;br /&gt;
*Silver Sharpie used for numbers&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Reasoning for Geometry of Design&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Equilateral Triangle:&amp;#039;&amp;#039;&lt;br /&gt;
By having the speakers equidistant from each other, we were able to create symmetry in our design, which made programming the various nodes much easier.  For example, we were able to use the same theory to find the node at 12 o&amp;#039;clock, 4 o&amp;#039;clock, and 8 o&amp;#039;clock.  If the speakers were not placed equidistant from each other, two speakers placed at equal amplitudes and opposite phases would not have created a sink in the exact middle of the two speakers.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Adjustable Legs:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We needed to make the legs adjustable since it is essential that the platform be perfectly level in order for the objects placed on the platform to move in expected patterns.  For example, if one leg is slightly shorter than the other two, the objects placed on the platform would tend to move towards that leg and we could no longer rely on symmetry to program the various nodes due to the effects of gravity.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Height of Platform:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Through our own experimentation and from [http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Professor Lynch&amp;#039;s research], we found that we needed to have the pivot point (i.e. the speaker diaphragm) significantly below the platform in order to create sinks.  At one point in the design process, we attempted to create a different pivot point by replacing the PVC with 1/2&amp;quot; outer diameter, 1/4&amp;quot; inner diameter Tygon 2001 tubing that only was able to bend in one point since it had stand-offs and screws inside the tube.  However, this replacement in a sense created two pivot points (the speaker diaphragm and the Tygon), causing the platform to only create sources and not sinks.  In addition, the different height of the pivot point may have also led to the plate acting differently.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
[[Image:Circuit_Photo_Team22.jpg|right|thumb|Circuit Board|200px]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Component List:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Price (Total)&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Microchip 8-bit PIC Microcontroller (U1)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Maxim Quad, 2-Wire Serial 8-Bit Digital-to-Analog Converter (U2)&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;MAX520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$9.28&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Emtel 150W, 12V Power Supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;EMV15012V&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Emtel EMV15012V Wiring Kit&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;61-EMV15012VWK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Legacy Series II 4-channel, 300W Power Amplifier&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LA160&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;N/A&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Keystone Electronics Snap-Fit 90 PC Phono Jack&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;901K-ND&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;3&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.digikey.com Digi-Key]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$3.81&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Radioshack 6-Ft. Shielded Cable, RCA Plug to RCA Plug&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;42-2367&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;3&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.radioshack.com Radioshack]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$14.97&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;20-ft Monster Cable 16-Gauge Speaker Wire&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S16-2XLN&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.radioshack.com Radioshack]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$9.97&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Circuit Diagram:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:team22_circuit.jpg|center|frame|Vibratory Clock Circuit Diagram|600px]]&lt;br /&gt;
&lt;br /&gt;
==Software Design==&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
[[Image:VibratoryClock.jpg|right|thumb|300px]]&lt;br /&gt;
&lt;br /&gt;
We were able to get our project working so that the plate moves an object placed anywhere on the plate to the correct time and then moves the objects around the clock face, acting as the hour &amp;quot;hand&amp;quot; of a clock.  However, we increased the speed so that it takes about 2 minutes for objects placed on the clock to move around so that it is easy to demonstrate.  Check out the working Vibratory Clock [http://www.youtube.com/watch?v=KhgTNCfdwZw here].&lt;br /&gt;
&lt;br /&gt;
==Reflections==&lt;br /&gt;
&lt;br /&gt;
==Useful Resources==&lt;br /&gt;
&lt;br /&gt;
[http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm Vibration-Induced Frictional Force Fields for Part Manipulation]&lt;br /&gt;
&lt;br /&gt;
[http://www.cs.berkeley.edu/~jfc/dreznik/UPM2000/index.html Universal Planar Manipulator]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Resistive_Touchscreen&amp;diff=8063</id>
		<title>Resistive Touchscreen</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Resistive_Touchscreen&amp;diff=8063"/>
		<updated>2008-03-20T07:39:22Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;NOTE: THIS INFORMATION PERTAINS TO ACCELEROMETER&amp;#039;S AND IS BEING USED HERE AS A PLACEMARKER. IT WILL BE REMOVED SHORTLY AND REPLACED WITH USEFUL SCHOLARLY INFORMATION VERY SOON.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:mems accelerometer.png|right]]&lt;br /&gt;
&lt;br /&gt;
Accelerometers measure linear acceleration and also gravity; the two are indistinguishable.  Thus they unavoidably function as tilt sensors as well.   Inexpensive 1, 2, and 3-axis accelerometers are available which are constructed with MEMS techniques.  &lt;br /&gt;
MEMS gyroscopes are also available, for measuring angular velocity, but are more expensive.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:carrier.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The LIS2L02AS4-TR accelerometer gives you a choice of +/-2g or +/-6g full scale.  It needs only a single +5V supply.  Its bandwidth is from DC to 1.5KHz.  The output is usually low-pass filtered in applications which do not need the full 1.5KHz bandwidth, using an external capacitor.&lt;br /&gt;
&lt;br /&gt;
The chip is available only in a surface-mount SO-24 package.  Fortunately an adapter socket (Digikey A322-ND) can be used to give the chip convenient DIP-24 legs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:somesoldered.jpg|right]]&lt;br /&gt;
Soldering the chip into the adapter socket is a little challenging.   Here are some tricks that make it easier.  The more of these you can take advantage of, the easier it will be.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Use a very fine pointed soldering iron and fine solder.&lt;br /&gt;
* Apply a bead of liquid flux to the pads, which will make the solder flow in between the pin and the pad enthusiastically.&lt;br /&gt;
* Tape the chip down onto its socket adapter.&lt;br /&gt;
* Have a magnifying lens or loupe available.&lt;br /&gt;
* Know which pins are not used.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The last point is especially useful.  Start with pin 1 which is NC (Not Connected), so that even if you get a solder blob connecting pins 1 &amp;amp; 2 that&amp;#039;s ok.  If the other pins are all aligned with their pads, pin 1&amp;#039;s solder will now hold them there.  If not, melt pin 1&amp;#039;s solder and adjust.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:chip.gif|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now solder only the other pins that are in use, as shown in red on the diagram.   Solder one or two on the opposite edge as well, for mechanical stability.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pins marked &amp;quot;reserved&amp;quot; should not be solder-blobbed to their neighbors because we don&amp;#039;t know what they connect to inside the chip.  Reserved is not the same thing as NC.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
[[Image:circuit.gif|right]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use a supply shunt near the chip (1uF) from +5 to ground).  Use low-pass filter capacitors on the outputs (called Cload in the diagram).  The output impedance of the chip is 110Kohm, so a 0.1uF capacitor gives a low pass time constant of ~10mS.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tie ST, PD low, and FS low for +/-2g full scale operation.  The output voltage ranges 0-5V, well matched to PIC inputs.  2.5V is the output when acceleration is zero and and the chip is horizontal (not tilted.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The circuit shows some optional buffer amplifiers to produce a low impedance output.&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Stepper_Motor_Circuits&amp;diff=7179</id>
		<title>Stepper Motor Circuits</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Stepper_Motor_Circuits&amp;diff=7179"/>
		<updated>2008-02-26T23:57:28Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Bipolar Stepper Driver Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Actuators]]&lt;br /&gt;
&lt;br /&gt;
==Basics==&lt;br /&gt;
To control a stepper motor, you have to energize each winding individually in a specific and timed order.  The energizing is accomplished by a driver circuit (an amplifier).  The timing is performed by an indexer circuit and the objective (go forward, go backward, brake, coast, etc.) is controlled by some external user interface, such as a computer or joystick.  The figure below shows this process.&lt;br /&gt;
&lt;br /&gt;
[[image:stepper motor block diagram.jpg|500px|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Drivers==&lt;br /&gt;
The circuits for driving unipolar and bipolar stepper motors differ because bipolar stepper motors don&amp;#039;t have a &amp;quot;center tap.&amp;quot;  However, it is possible to use bipolar drivers to drive unipolar steppers after some small modifications.&lt;br /&gt;
&lt;br /&gt;
Care must be taken in the driver circuit to protect against voltage spikes.  Because the motor windings are inductors, switching off the power to the winding produces a short burst of voltage.  To protect against this, always put a diode in parallel with the winding, making sure the diode can handle the winding current.  This is shown in the following figure.&lt;br /&gt;
&lt;br /&gt;
[[image:winding diagram.jpg|200px|center]]&lt;br /&gt;
&lt;br /&gt;
===Unipolar Stepper Driver Circuit===&lt;br /&gt;
&lt;br /&gt;
The basic drive circuitry for a single unipolar winding is shown in the following figure.&lt;br /&gt;
&lt;br /&gt;
[[image:unipolar driver digram.jpg|300px|center]]&lt;br /&gt;
&lt;br /&gt;
For the switches, any kind of switching technology can be used.  The following figure shows two such switches.  The first one uses a power darlington transistor and the second one uses a power field effect transistor.&lt;br /&gt;
&lt;br /&gt;
[[image:unipolar switch circuits.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
For driving a full stepper motor, with multiple coils, you can either build each of the above circuits individually, or you can use a integrated chip.  One such chip is the [[media:DS2003.pdf|DS2003]], which is a darlington array, and is shown below.  This chip can be used when the total current to each winding is less than 500 milliamps.&lt;br /&gt;
&lt;br /&gt;
[[image:ds2003.png|center|300px]]&lt;br /&gt;
&lt;br /&gt;
===Bipolar Stepper Driver Circuit===&lt;br /&gt;
&lt;br /&gt;
Bipolar stepper drivers use H-bridges to energize the windings of the motor.  H-bridges allow you to choose the direction of the current through the winding.  Using an H-bridge configuration, there are four transistors for each winding as shown in the first figure below.  However, most of the time they are prewired together so that only two inputs are needed.  This makes generating pulses easier and also serves to protect against short circuits.  This circuit is shown in the second figure below.&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[image:bipolar4input.png|280px]]&lt;br /&gt;
| [[image:bipolar2input.png]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The table below shows the result of each possible control input.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
! XY !! ABCD !! Mode&lt;br /&gt;
|-&lt;br /&gt;
| 00 || 0000 || coast&lt;br /&gt;
|-&lt;br /&gt;
| 01 || 1001 || forward&lt;br /&gt;
|-&lt;br /&gt;
| 10 || 0110 || reverse&lt;br /&gt;
|-&lt;br /&gt;
| 11 || 1111 || brake&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You should be able to drive a bipolar motor with a unipolar motor circuit.  The only difference is that there are no center winding taps to connect to the power source.  Somebody correct me?&lt;br /&gt;
&lt;br /&gt;
==Indexing==&lt;br /&gt;
&lt;br /&gt;
There are many methods of producing the index pulses needed to drive stepper motors.  This can either be done using a microprocessor or an integrated circuit.  The calculations will most likely be so burdensome that the microprocessor would be unable to do any other calculations while producing the pulse trains.  However, there are many cheap microcontrollers available these days and they could be used as dedicated indexers.&lt;br /&gt;
&lt;br /&gt;
Most indexers have similar inputs and are intended to control the speed and direction of the motor.  The logic diagram shows how this is accomplished.&lt;br /&gt;
&lt;br /&gt;
[[image:indexer.png|center]]&lt;br /&gt;
&lt;br /&gt;
===L297=== &lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Digikey Part #: 497-1394-5-ND&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The [[media:L297.pdf|L297]] is a 20-pin DIP chip that was designed specifically to control either unipolar or bipolar stepper motors.  It will control two H-bridges to power two windings.  Its inputs control the speed and direction of the motor.  The diagram below shows the typical setup of the circuit.  The A and B outputs would correspond to the X and Y inputs on the H-bridge of the first winding (see above).  Likewise, the C and D outputs would correspond to the X and Y inputs on the second winding.&lt;br /&gt;
&lt;br /&gt;
[[image:l297.png|center]]&lt;br /&gt;
&lt;br /&gt;
This chip was specifically designed to interface with the L298N stepper motor driver chip, which is also found in the lab.  [[media:L297 and L298.pdf|See this document]].&lt;br /&gt;
&lt;br /&gt;
===[[PIC16F684]]===&lt;br /&gt;
&lt;br /&gt;
The PIC16F684, which is available in the lab, is a good programmable microcontroller ideally suited for controlling stepper motors.&lt;br /&gt;
&lt;br /&gt;
[[media:PIC Stepper Control.pdf|Read this document]]&lt;br /&gt;
&lt;br /&gt;
==Integrated Circuits==&lt;br /&gt;
&lt;br /&gt;
===MC3479===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Allied Electronics Part #: 568-9170&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The MC3479 is a single-chip stepper motor driver that can handle 350mA per winding.  There are several high-level digital inputs that control the speed and direction of the motor.  The first figure below shows the internal circuitry and the second picture shows a typical setup.&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[image:mc3479.png|center]]&lt;br /&gt;
|-&lt;br /&gt;
| [[image:mc3479 circuit.png|center]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* &amp;quot;Stepper Motor Basics&amp;quot;, http://www.ams2000.com/pdf/step101.pdf&lt;br /&gt;
* &amp;quot;Jones on Stepping Motor Control Circuits&amp;quot;, http://www.cs.uiowa.edu/~jones/step/circuits.html&lt;br /&gt;
* MC3479, http://www.onsemi.com/pub/Collateral/MC3479-D.PDF&lt;br /&gt;
* L297, http://www.st.com/stonline/books/pdf/docs/1334.pdf&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7150</id>
		<title>Microphones</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7150"/>
		<updated>2008-02-21T05:07:01Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
This project is to demonstrate a &amp;quot;clapper&amp;quot; device using an electret microphone (e.g., the 423-1024-ND from digikey).  Build an appropriate circuit and write a program to continuously display the volume of the sound it receives as a &amp;quot;light bar&amp;quot; on the PIC board LEDs.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;clapper&amp;quot; device was built using a PIC 18F4520 and an [http://en.wikipedia.org/wiki/Electret_microphone electret condenser microphone] (in this case, the [http://www.knowles.com/search/prods_pdf/MD9745APA-1.pdf 423-1024-ND] from digikey) as an analog input. The device operates on the principle that the microphone will convert the sound into an analog input to the PIC and, as the sound increases in volume, the analog input&amp;#039;s amplitude will increase. This input is then converted into an output on the set of LEDs soldered onto the PIC&amp;#039;s circuit board. This output works as a light bar; it displays the minimum one LED for quiet sound levels and activates additional LEDs as the sound becomes louder -- up to a maximum of eight.  The sensitivity of the microphone is adjustable through a gain potentiometer. &lt;br /&gt;
&lt;br /&gt;
[[image:ElectretMicrophone.gif|thumb|300px|[[Interior of Electret Microphone]]|right]]&lt;br /&gt;
[[image:Electret_condenser_microphone_capsules.jpg|thumb|350px|[[Electret condenser microphone capsules]]|left]]&lt;br /&gt;
&lt;br /&gt;
The most commonly used microphones for audio use capacitance charge (condenser microphones), electromagnetic generation (dynamic microphones), or piezoelectric generation.  In a [http://en.wikipedia.org/wiki/Condenser_microphone#Condenser.2C_capacitor_or_electrostatic_microphones condenser microphone], a thin membrane of the microphone acts as one plate of a capacitor and a nearly constant charge is maintained on the capacitor. The voltage maintained across the capacitor plates changes with the vibrations in the air, according to the capacitance equation: &lt;br /&gt;
:&amp;lt;math&amp;gt;Q = C \cdot V&amp;lt;/math&amp;gt;  where Q = charge in coulombs, C = capacitance in farads and V = potential difference in volts, resulting in a change in output voltage. Power is necessary for establishing the capacitor plate voltage, and is also needed for internal amplification of the signal to a useful output level. Electret microphones, a type of condenser microphone, replace the externally-applied charge with a permanently fixed-charged material.  The electret is a stable dielectric material with a permanently-embedded static charge. Electret microphones require no polarizing voltage but, due to their integrated pre-amplifier, require a small amount of power either from microphone inputs as phantom power or from a small battery. Due to mass-production of these devices, electret microphones lack the precision needed for high-quality microphones.&lt;br /&gt;
&lt;br /&gt;
Due to the variable nature of ambient noise, a calibration &amp;quot;reset&amp;quot; button was included that would reset the output LEDs based on the environment&amp;#039;s baseline noise level. This calibration was done via software averaging of the ambient volume level. The device that is built currently follows the principles of the clapper device in that the higher the analog input is received, the more LEDs will be shown. However, due to the brevity of the audio input peak for shorter signals such as a clap, it is sometimes difficult to see the correspondingly brief output.  A further step would be to install a software switch that would detect the characteristic sound pattern of a clap and activate a digital output upon recognition.&lt;br /&gt;
&lt;br /&gt;
Of the three microphones tested for the clapper device (Electret Microphone, [http://www.sonystyle.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=10551&amp;amp;storeId=10151&amp;amp;langId=-1&amp;amp;productId=11037550 Sony F-V100], and a small dynamic microphone), the electret microphone showed the greatest sensitivity to varying noise levels.&lt;br /&gt;
&lt;br /&gt;
=== Problems ===&lt;br /&gt;
&lt;br /&gt;
We ran into several problems using this configuration, and other configurations similar to this one. First of all, the sensitivity of the microphone was  poor even at the most sensitive potentiometer setting. Because of the way the code worked, we were able to register a loud clap within about a foot of the microphone, but we weren&amp;#039;t able to get a good response from a constant sound, like a hum. This would work well for a device that just needed to register when a loud noise occurs, but would not be suitable for any sort of recording or signal processing.&lt;br /&gt;
&lt;br /&gt;
Another approach we tried was to run the signal through a simple non-inverting [[Operational Amplifiers (Op-Amps) | operational amplifier]]. This was even less successful as it amplified the noise to the level where a clap or hum was indistinguishable from the noise. We experimented with a gain of 2 and a gain of 11. The gain of 2 made no significant difference and the gain of 11 simply amplified too much noise.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
The circuit built for this example uses an electret microphone to listen to external sound and displays the volume level as a light bar on the PIC board LEDs.  The microphone uses a single analog input pin of the PIC.&lt;br /&gt;
&lt;br /&gt;
Optional features present in the shown circuit diagram include a potentiometer gain knob for adjusting the microphone&amp;#039;s sensitivity and a calibration button for setting the baseline ambient noise level.  The code governing the operation of the calibration button is included below; the button itself is wired into a digital input of the PIC. Refer to the photo and diagram for details. Although the potentiometer is good for calibration, we found that we can get a decent sensitivity by simply using a 2.2K-ohm resistor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:400px-Microphone_circuit.JPG|thumb|400px|[[Microphone Circuit and PIC photo]]|right]] [[image:Mic_circuit_diagram4.JPG|thumb|400px|[[Microphone Circuit and PIC diagram]]|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
microphone.c by JJ Darling, Alex Leung, Ben Schriesheim&lt;br /&gt;
This code will take an analog microphone input and display the power of the single &lt;br /&gt;
as an easily read LED array. One light on means the input matches the ambient noise,&lt;br /&gt;
and all eight lights on means the microphone is receiving a loud noise.&lt;br /&gt;
&lt;br /&gt;
The reset button can be used to match the lowest output to the ambient noise.&lt;br /&gt;
&lt;br /&gt;
This code was derived off of the analog input code written by Prof. Michael Peshkin, which&lt;br /&gt;
can be found in the source code repository on this wiki.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#DEVICE ADC=8                  // set ADC to 8 bit accuracy.&lt;br /&gt;
&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
signed int16 value;&lt;br /&gt;
int16 valueinit=0;&lt;br /&gt;
int k=0;&lt;br /&gt;
void initialize();&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_adc_ports(AN0);        // Enable analog inputs AN0;&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);     &lt;br /&gt;
   initialize(); &lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
   &lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      &lt;br /&gt;
      if (input(PIN_C0)&amp;gt;0)  initialize();   //Initialize the base output to match ambient noise&lt;br /&gt;
      &lt;br /&gt;
      value = read_adc();     // now you can read ADC as frequently as you like&lt;br /&gt;
      &lt;br /&gt;
      //Create a gain to dramatically differentiate the input level from ambient noise&lt;br /&gt;
      if ((value-valueinit)&amp;lt;0) value=0;   &lt;br /&gt;
      value=(value-valueinit)*20;&lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;lt;32)              //Easy to read volume meter&lt;br /&gt;
      output_d(0b1);&lt;br /&gt;
   else if (value&amp;lt;64)&lt;br /&gt;
      output_d(0b11);&lt;br /&gt;
   else if (value&amp;lt;96)&lt;br /&gt;
      output_d(0b111);&lt;br /&gt;
   else if (value&amp;lt;128)&lt;br /&gt;
      output_d(0b1111);&lt;br /&gt;
   else if (value&amp;lt;160)&lt;br /&gt;
      output_d(0b11111);&lt;br /&gt;
   else if (value&amp;lt;192)&lt;br /&gt;
      output_d(0b111111);&lt;br /&gt;
   else if (value&amp;lt;224)&lt;br /&gt;
      output_d(0b1111111);&lt;br /&gt;
   else&lt;br /&gt;
      output_d(0b11111111);           &lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;gt;128) delay_ms(200);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Take samples to establish an initial value to &amp;#039;tare&amp;#039; the ambient noise.&lt;br /&gt;
void initialize() {&lt;br /&gt;
   &lt;br /&gt;
   delay_ms(1000);       //Give enough time for the user to release the &amp;quot;reset&amp;quot; button     &lt;br /&gt;
   &lt;br /&gt;
   valueinit=0;&lt;br /&gt;
   &lt;br /&gt;
   //Read 100 input levels and take their average. This a measure of the ambient noise&lt;br /&gt;
   for (k=0;k&amp;lt;100;k++) &lt;br /&gt;
   {&lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      valueinit+=read_adc();&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   valueinit = (valueinit/100);&lt;br /&gt;
   &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
1. [http://en.wikipedia.org/wiki/Microphone Microphone - From Wikipedia, the free encyclopedia] &amp;lt;br&amp;gt;&lt;br /&gt;
2. [http://www.national.com/nationaledge/dec02/article.html Integrated Circuits for High Performance Electret Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
[http://www.hosiden.co.jp/web/english/web/products/pdf/e_on06_mic.pdf Guide for Electret Condenser Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.soundonsound.com/sos/1995_articles/jun95/microphones.html CHOOSING A MICROPHONE: Microphone types and uses] &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7149</id>
		<title>Microphones</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7149"/>
		<updated>2008-02-21T04:57:50Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
This project is to demonstrate a &amp;quot;clapper&amp;quot; device using an electret microphone (e.g., the 423-1024-ND from digikey).  Build an appropriate circuit and write a program to continuously display the volume of the sound it receives as a &amp;quot;light bar&amp;quot; on the PIC board LEDs.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;clapper&amp;quot; device was built using a PIC 18F4520 and an [http://en.wikipedia.org/wiki/Electret_microphone electret condenser microphone] (in this case, the [http://www.knowles.com/search/prods_pdf/MD9745APA-1.pdf 423-1024-ND] from digikey) as an analog input. The device operates on the principle that the microphone will convert the sound into an analog input to the PIC and, as the sound increases in volume, the analog input&amp;#039;s amplitude will increase. This input is then converted into an output on the set of LEDs soldered onto the PIC&amp;#039;s circuit board. This output works as a light bar; it displays the minimum one LED for quiet sound levels and activates additional LEDs as the sound becomes louder -- up to a maximum of eight.  The sensitivity of the microphone is adjustable through a gain potentiometer. &lt;br /&gt;
&lt;br /&gt;
[[image:ElectretMicrophone.gif|thumb|300px|[[Interior of Electret Microphone]]|right]]&lt;br /&gt;
[[image:Electret_condenser_microphone_capsules.jpg|thumb|350px|[[Electret condenser microphone capsules]]|left]]&lt;br /&gt;
&lt;br /&gt;
The most commonly used microphones for audio use capacitance charge (condenser microphones), electromagnetic generation (dynamic microphones), or piezoelectric generation.  In a [http://en.wikipedia.org/wiki/Condenser_microphone#Condenser.2C_capacitor_or_electrostatic_microphones condenser microphone], a thin membrane of the microphone acts as one plate of a capacitor and a nearly constant charge is maintained on the capacitor. The voltage maintained across the capacitor plates changes with the vibrations in the air, according to the capacitance equation: &lt;br /&gt;
:&amp;lt;math&amp;gt;Q = C \cdot V&amp;lt;/math&amp;gt;  where Q = charge in coulombs, C = capacitance in farads and V = potential difference in volts, resulting in a change in output voltage. Power is necessary for establishing the capacitor plate voltage, and is also needed for internal amplification of the signal to a useful output level. Electret microphones, a type of condenser microphone, replace the externally-applied charge with a permanently fixed-charged material.  The electret is a stable dielectric material with a permanently-embedded static charge. Electret microphones require no polarizing voltage but, due to their integrated pre-amplifier, require a small amount of power either from microphone inputs as phantom power or from a small battery. Due to mass-production of these devices, electret microphones lack the precision needed for high-quality microphones.&lt;br /&gt;
&lt;br /&gt;
Due to the variable nature of ambient noise, a calibration &amp;quot;reset&amp;quot; button was included that would reset the output LEDs based on the environment&amp;#039;s baseline noise level. This calibration was done via software averaging of the ambient volume level. The device that is built currently follows the principles of the clapper device in that the higher the analog input is received, the more LEDs will be shown. However, due to the brevity of the audio input peak for shorter signals such as a clap, it is sometimes difficult to see the correspondingly brief output.  A further step would be to install a software switch that would detect the characteristic sound pattern of a clap and activate a digital output upon recognition.&lt;br /&gt;
&lt;br /&gt;
Of the three microphones tested for the clapper device (Electret Microphone, [http://www.sonystyle.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=10551&amp;amp;storeId=10151&amp;amp;langId=-1&amp;amp;productId=11037550 Sony F-V100], and a small dynamic microphone), the electret microphone showed the greatest sensitivity to varying noise levels.&lt;br /&gt;
&lt;br /&gt;
=== Problems ===&lt;br /&gt;
&lt;br /&gt;
We ran into several problems using this configuration, and other configurations similar to this one. First of all, the sensitivity of the microphone was  poor even at the most sensitive potentiometer setting. Because of the way the code worked, we were able to register a loud clap within about a foot of the microphone, but we weren&amp;#039;t able to get a good response from a constant sound, like a hum. This would work well for a device that just needed to register when a loud noise occurs, but would not be suitable for any sort of recording or signal processing.&lt;br /&gt;
&lt;br /&gt;
Another approach we tried was to run the signal through a simple non-inverting [[Operational Amplifiers (Op-Amps) | operational amplifier]]. This was even less successful as it amplified the noise to the level where a clap or hum was indistinguishable from the noise. We experimented with a gain of 2 and a gain of 11. The gain of 2 made no significant difference and the gain of 11 simply amplified too much noise.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
The circuit built for this example uses an electret microphone to listen to external sound and displays the volume level as a light bar on the PIC board LEDs.  The microphone uses a single analog input pin of the PIC.&lt;br /&gt;
&lt;br /&gt;
Optional features present in the shown circuit diagram include a potentiometer gain knob for adjusting the microphone&amp;#039;s sensitivity and a calibration button for setting the baseline ambient noise level.  The code governing the operation of the calibration button is included below; the button itself is wired into a digital input of the PIC. Refer to the photo and diagram for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:400px-Microphone_circuit.JPG|thumb|400px|[[Microphone Circuit and PIC photo]]|right]] [[image:Mic_circuit_diagram4.JPG|thumb|400px|[[Microphone Circuit and PIC diagram]]|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
microphone.c by JJ Darling, Alex Leung, Ben Schriesheim&lt;br /&gt;
This code will take an analog microphone input and display the power of the single &lt;br /&gt;
as an easily read LED array. One light on means the input matches the ambient noise,&lt;br /&gt;
and all eight lights on means the microphone is receiving a loud noise.&lt;br /&gt;
&lt;br /&gt;
The reset button can be used to match the lowest output to the ambient noise.&lt;br /&gt;
&lt;br /&gt;
This code was derived off of the analog input code written by Prof. Michael Peshkin, which&lt;br /&gt;
can be found in the source code repository on this wiki.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#DEVICE ADC=8                  // set ADC to 8 bit accuracy.&lt;br /&gt;
&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
signed int16 value;&lt;br /&gt;
int16 valueinit=0;&lt;br /&gt;
int k=0;&lt;br /&gt;
void initialize();&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_adc_ports(AN0);        // Enable analog inputs AN0;&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);     &lt;br /&gt;
   initialize(); &lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
   &lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      &lt;br /&gt;
      if (input(PIN_C0)&amp;gt;0)  initialize();   //Initialize the base output to match ambient noise&lt;br /&gt;
      &lt;br /&gt;
      value = read_adc();     // now you can read ADC as frequently as you like&lt;br /&gt;
      &lt;br /&gt;
      //Create a gain to dramatically differentiate the input level from ambient noise&lt;br /&gt;
      if ((value-valueinit)&amp;lt;0) value=0;   &lt;br /&gt;
      value=(value-valueinit)*20;&lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;lt;32)              //Easy to read volume meter&lt;br /&gt;
      output_d(0b1);&lt;br /&gt;
   else if (value&amp;lt;64)&lt;br /&gt;
      output_d(0b11);&lt;br /&gt;
   else if (value&amp;lt;96)&lt;br /&gt;
      output_d(0b111);&lt;br /&gt;
   else if (value&amp;lt;128)&lt;br /&gt;
      output_d(0b1111);&lt;br /&gt;
   else if (value&amp;lt;160)&lt;br /&gt;
      output_d(0b11111);&lt;br /&gt;
   else if (value&amp;lt;192)&lt;br /&gt;
      output_d(0b111111);&lt;br /&gt;
   else if (value&amp;lt;224)&lt;br /&gt;
      output_d(0b1111111);&lt;br /&gt;
   else&lt;br /&gt;
      output_d(0b11111111);           &lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;gt;128) delay_ms(200);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Take samples to establish an initial value to &amp;#039;tare&amp;#039; the ambient noise.&lt;br /&gt;
void initialize() {&lt;br /&gt;
   &lt;br /&gt;
   delay_ms(1000);       //Give enough time for the user to release the &amp;quot;reset&amp;quot; button     &lt;br /&gt;
   &lt;br /&gt;
   valueinit=0;&lt;br /&gt;
   &lt;br /&gt;
   //Read 100 input levels and take their average. This a measure of the ambient noise&lt;br /&gt;
   for (k=0;k&amp;lt;100;k++) &lt;br /&gt;
   {&lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      valueinit+=read_adc();&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   valueinit = (valueinit/100);&lt;br /&gt;
   &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
1. [http://en.wikipedia.org/wiki/Microphone Microphone - From Wikipedia, the free encyclopedia] &amp;lt;br&amp;gt;&lt;br /&gt;
2. [http://www.national.com/nationaledge/dec02/article.html Integrated Circuits for High Performance Electret Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
[http://www.hosiden.co.jp/web/english/web/products/pdf/e_on06_mic.pdf Guide for Electret Condenser Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.soundonsound.com/sos/1995_articles/jun95/microphones.html CHOOSING A MICROPHONE: Microphone types and uses] &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7148</id>
		<title>Microphones</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7148"/>
		<updated>2008-02-21T04:41:51Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
This project is to demonstrate a &amp;quot;clapper&amp;quot; device using an electret microphone (e.g., the 423-1024-ND from digikey).  Build an appropriate circuit and write a program to continuously display the volume of the sound it receives as a &amp;quot;light bar&amp;quot; on the PIC board LEDs.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;clapper&amp;quot; device was built using a PIC 18F4520 and an [http://en.wikipedia.org/wiki/Electret_microphone electret condenser microphone] (in this case, the [http://www.knowles.com/search/prods_pdf/MD9745APA-1.pdf 423-1024-ND] from digikey) as an analog input. The device operates on the principle that the microphone will convert the sound into an analog input to the PIC and, as the sound increases in volume, the analog input&amp;#039;s amplitude will increase. This input is then converted into an output on the set of LEDs soldered onto the PIC&amp;#039;s circuit board. This output works as a light bar; it displays the minimum one LED for quiet sound levels and activates additional LEDs as the sound becomes louder -- up to a maximum of eight.  The sensitivity of the microphone is adjustable through a gain potentiometer. &lt;br /&gt;
&lt;br /&gt;
[[image:ElectretMicrophone.gif|thumb|300px|[[Interior of Electret Microphone]]|right]]&lt;br /&gt;
[[image:Electret_condenser_microphone_capsules.jpg|thumb|350px|[[Electret condenser microphone capsules]]|left]]&lt;br /&gt;
&lt;br /&gt;
The most commonly used microphones for audio use capacitance charge (condenser microphones), electromagnetic generation (dynamic microphones), or piezoelectric generation.  In a [http://en.wikipedia.org/wiki/Condenser_microphone#Condenser.2C_capacitor_or_electrostatic_microphones condenser microphone], a thin membrane of the microphone acts as one plate of a capacitor and a nearly constant charge is maintained on the capacitor. The voltage maintained across the capacitor plates changes with the vibrations in the air, according to the capacitance equation: &lt;br /&gt;
:&amp;lt;math&amp;gt;Q = C \cdot V&amp;lt;/math&amp;gt;  where Q = charge in coulombs, C = capacitance in farads and V = potential difference in volts, resulting in a change in output voltage. Power is necessary for establishing the capacitor plate voltage, and is also needed for internal amplification of the signal to a useful output level. Electret microphones, a type of condenser microphone, replace the externally-applied charge with a permanently fixed-charged material.  The electret is a stable dielectric material with a permanently-embedded static charge. Electret microphones require no polarizing voltage but, due to their integrated pre-amplifier, require a small amount of power either from microphone inputs as phantom power or from a small battery. Due to mass-production of these devices, electret microphones lack the precision needed for high-quality microphones.&lt;br /&gt;
&lt;br /&gt;
Due to the variable nature of ambient noise, a calibration &amp;quot;reset&amp;quot; button was included that would reset the output LEDs based on the environment&amp;#039;s baseline noise level. This calibration was done via software averaging of the ambient volume level. The device that is built currently follows the principles of the clapper device in that the higher the analog input is received, the more LEDs will be shown. However, due to the brevity of the audio input peak for shorter signals such as a clap, it is sometimes difficult to see the correspondingly brief output.  A further step would be to install a software switch that would detect the characteristic sound pattern of a clap and activate a digital output upon recognition.&lt;br /&gt;
&lt;br /&gt;
Of the three microphones tested for the clapper device (Electret Microphone, [http://www.sonystyle.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=10551&amp;amp;storeId=10151&amp;amp;langId=-1&amp;amp;productId=11037550 Sony F-V100], and a small dynamic microphone), the electret microphone showed the greatest sensitivity to varying noise levels.&lt;br /&gt;
&lt;br /&gt;
=== Problems ===&lt;br /&gt;
&lt;br /&gt;
We ran into several problems using this configuration, and other configurations similar to this one. First of all, the sensitivity of the microphone was  poor even at the most sensitive potentiometer setting. Because of the way the code worked, we were able to register a loud clap within about a foot of the microphone, but we weren&amp;#039;t able to get a good response from a constant sound, like a hum. This would work well for a device that just needed to register when a loud noise occurs, but would not be suitable for any sort of recording or signal processing.&lt;br /&gt;
&lt;br /&gt;
Another approach we tried was to run the signal through a simple non-inverting operational amplifier. This was even less successful as it amplified the noise to the level where a clap or hum was indistinguishable from the noise. We experimented with a gain of 2 and a gain of 11. The gain of 2 made no significant difference and the gain of 11 simply amplified too much noise.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
The circuit built for this example uses an electret microphone to listen to external sound and displays the volume level as a light bar on the PIC board LEDs.  The microphone uses a single analog input pin of the PIC.&lt;br /&gt;
&lt;br /&gt;
Optional features present in the shown circuit diagram include a potentiometer gain knob for adjusting the microphone&amp;#039;s sensitivity and a calibration button for setting the baseline ambient noise level.  The code governing the operation of the calibration button is included below; the button itself is wired into a digital input of the PIC. Refer to the photo and diagram for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:400px-Microphone_circuit.JPG|thumb|400px|[[Microphone Circuit and PIC photo]]|right]] [[image:Mic_circuit_diagram4.JPG|thumb|400px|[[Microphone Circuit and PIC diagram]]|left]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
microphone.c by JJ Darling, Alex Leung, Ben Schriesheim&lt;br /&gt;
This code will take an analog microphone input and display the power of the single &lt;br /&gt;
as an easily read LED array. One light on means the input matches the ambient noise,&lt;br /&gt;
and all eight lights on means the microphone is receiving a loud noise.&lt;br /&gt;
&lt;br /&gt;
The reset button can be used to match the lowest output to the ambient noise.&lt;br /&gt;
&lt;br /&gt;
This code was derived off of the analog input code written by Prof. Michael Peshkin, which&lt;br /&gt;
can be found in the source code repository on this wiki.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#DEVICE ADC=8                  // set ADC to 8 bit accuracy.&lt;br /&gt;
&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
signed int16 value;&lt;br /&gt;
int16 valueinit=0;&lt;br /&gt;
int k=0;&lt;br /&gt;
void initialize();&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_adc_ports(AN0);        // Enable analog inputs AN0;&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);     &lt;br /&gt;
   initialize(); &lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
   &lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      &lt;br /&gt;
      if (input(PIN_C0)&amp;gt;0)  initialize();   //Initialize the base output to match ambient noise&lt;br /&gt;
      &lt;br /&gt;
      value = read_adc();     // now you can read ADC as frequently as you like&lt;br /&gt;
      &lt;br /&gt;
      //Create a gain to dramatically differentiate the input level from ambient noise&lt;br /&gt;
      if ((value-valueinit)&amp;lt;0) value=0;   &lt;br /&gt;
      value=(value-valueinit)*20;&lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;lt;32)              //Easy to read volume meter&lt;br /&gt;
      output_d(0b1);&lt;br /&gt;
   else if (value&amp;lt;64)&lt;br /&gt;
      output_d(0b11);&lt;br /&gt;
   else if (value&amp;lt;96)&lt;br /&gt;
      output_d(0b111);&lt;br /&gt;
   else if (value&amp;lt;128)&lt;br /&gt;
      output_d(0b1111);&lt;br /&gt;
   else if (value&amp;lt;160)&lt;br /&gt;
      output_d(0b11111);&lt;br /&gt;
   else if (value&amp;lt;192)&lt;br /&gt;
      output_d(0b111111);&lt;br /&gt;
   else if (value&amp;lt;224)&lt;br /&gt;
      output_d(0b1111111);&lt;br /&gt;
   else&lt;br /&gt;
      output_d(0b11111111);           &lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;gt;128) delay_ms(200);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Take samples to establish an initial value to &amp;#039;tare&amp;#039; the ambient noise.&lt;br /&gt;
void initialize() {&lt;br /&gt;
   &lt;br /&gt;
   delay_ms(1000);       //Give enough time for the user to release the &amp;quot;reset&amp;quot; button     &lt;br /&gt;
   &lt;br /&gt;
   valueinit=0;&lt;br /&gt;
   &lt;br /&gt;
   //Read 100 input levels and take their average. This a measure of the ambient noise&lt;br /&gt;
   for (k=0;k&amp;lt;100;k++) &lt;br /&gt;
   {&lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      valueinit+=read_adc();&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   valueinit = (valueinit/100);&lt;br /&gt;
   &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
1. [http://en.wikipedia.org/wiki/Microphone Microphone - From Wikipedia, the free encyclopedia] &amp;lt;br&amp;gt;&lt;br /&gt;
2. [http://www.national.com/nationaledge/dec02/article.html Integrated Circuits for High Performance Electret Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
[http://www.hosiden.co.jp/web/english/web/products/pdf/e_on06_mic.pdf Guide for Electret Condenser Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.soundonsound.com/sos/1995_articles/jun95/microphones.html CHOOSING A MICROPHONE: Microphone types and uses] &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7028</id>
		<title>Microphones</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7028"/>
		<updated>2008-02-19T22:45:39Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
This project is to demonstrate a &amp;quot;clapper&amp;quot; device using an electret microphone (e.g., the 423-1024-ND from digikey).  Build an appropriate circuit and write a program to continuously display the volume of the sound it receives as a &amp;quot;light bar&amp;quot; on the PIC board LEDs.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;clapper&amp;quot; device will be built using a PIC 18F4520 and an [http://en.wikipedia.org/wiki/Electret_microphone electret microphone] (in this case, the [http://www.knowles.com/search/prods_pdf/MD9745APA-1.pdf 423-1024-ND] from digikey) as an analog input. The device operates on the principle that the microphone will convert the sound into an analog input to the PIC and as the sound increases in volume, the analog input&amp;#039;s amplitude will increase. This input is then converted into an output on the set of LEDs soldered onto the PIC&amp;#039;s circuit board. This output works as a light bar; it displays the minimum one LED for quiet sound levels and activates additional LEDs as the sound becomes louder -- up to a maximum of eight.  The sensitivity of the microphone is adjustable through a gain potentiometer. &lt;br /&gt;
&lt;br /&gt;
[[image:ElectretMicrophone.gif|right|350px|[[help:contents|Interior of Electret Microphone]]]]&lt;br /&gt;
[[image:Electret_condenser_microphone_capsules.jpg|right|350px|[[help:contents|Electret condenser microphone capsules]]]]&lt;br /&gt;
&lt;br /&gt;
Electret microphones work &lt;br /&gt;
&lt;br /&gt;
Due to the variable nature of ambient noise, a calibration &amp;quot;reset&amp;quot; button was included that would reset the output LEDs based on the environment&amp;#039;s baseline noise level. This calibration was done via software averaging of the ambient volume level. The device that is built currently follows the principles of the &amp;quot;clapper&amp;quot; device in that the higher the analog input is received, the more LEDs will be shown. However, due to the brevity of the audio input peak for shorter signals such as a clap, it is sometimes difficult to see the correspondingly brief output.  A further step would be to install a software switch that would detect the characteristic sound pattern of a clap and activate a digital output upon recognition.&lt;br /&gt;
&lt;br /&gt;
Of the three microphones tested (Electret Microphone, [http://www.sonystyle.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=10551&amp;amp;storeId=10151&amp;amp;langId=-1&amp;amp;productId=11037550 Sony F-V100], and a small dynamic microphone), the electret microphone showed the greatest sensitivity to varying noise levels.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
The circuit built for this example uses an electret microphone to listen to external sound and displays the volume level as a light bar on the PIC board LEDs.  The microphone uses a single analog input pin of the PIC.&lt;br /&gt;
&lt;br /&gt;
Optional features present in the shown circuit diagram include a potentiometer gain knob for adjusting the microphone&amp;#039;s sensitivity and a calibration button for setting the baseline ambient noise level.  The code governing the operation of the calibration button is included below; the button itself is wired into a digital input of the PIC. Refer to the photo and diagram for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:400px-Microphone_circuit.JPG|left|400px|[[help:contents|Microphone Circuit and PIC photo]]]] [[image:Mic_circuit_diagram4.JPG|right|450px|[[help:contents|Microphone Circuit and PIC diagram]]]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
microphone.c by JJ Darling, Alex Leung, Ben Schriesheim&lt;br /&gt;
This code will take an analog microphone input and display the power of the single &lt;br /&gt;
as an easily read LED array. One light on means the input matches the ambient noise,&lt;br /&gt;
and all eight lights on means the microphone is receiving a loud noise.&lt;br /&gt;
&lt;br /&gt;
The reset button can be used to match the lowest output to the ambient noise.&lt;br /&gt;
&lt;br /&gt;
This code was derived off of the analog input code written by Prof. Michael Peshkin, which&lt;br /&gt;
can be found in the source code repository on this wiki.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#DEVICE ADC=8                  // set ADC to 8 bit accuracy.&lt;br /&gt;
&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
signed int16 value;&lt;br /&gt;
int16 valueinit=0;&lt;br /&gt;
int k=0;&lt;br /&gt;
void initialize();&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_adc_ports(AN0);        // Enable analog inputs AN0;&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);     &lt;br /&gt;
   initialize(); &lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
   &lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      &lt;br /&gt;
      if (input(PIN_C0)&amp;gt;0)  initialize();   //Initialize the base output to match ambient noise&lt;br /&gt;
      &lt;br /&gt;
      value = read_adc();     // now you can read ADC as frequently as you like&lt;br /&gt;
      &lt;br /&gt;
      //Create a gain to dramatically differentiate the input level from ambient noise&lt;br /&gt;
      if ((value-valueinit)&amp;lt;0) value=0;   &lt;br /&gt;
      value=(value-valueinit)*20;&lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;lt;32)              //Easy to read volume meter&lt;br /&gt;
      output_d(0b1);&lt;br /&gt;
   else if (value&amp;lt;64)&lt;br /&gt;
      output_d(0b11);&lt;br /&gt;
   else if (value&amp;lt;96)&lt;br /&gt;
      output_d(0b111);&lt;br /&gt;
   else if (value&amp;lt;128)&lt;br /&gt;
      output_d(0b1111);&lt;br /&gt;
   else if (value&amp;lt;160)&lt;br /&gt;
      output_d(0b11111);&lt;br /&gt;
   else if (value&amp;lt;192)&lt;br /&gt;
      output_d(0b111111);&lt;br /&gt;
   else if (value&amp;lt;224)&lt;br /&gt;
      output_d(0b1111111);&lt;br /&gt;
   else&lt;br /&gt;
      output_d(0b11111111);           &lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;gt;128) delay_ms(200);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Take samples to establish an initial value to &amp;#039;tare&amp;#039; the ambient noise.&lt;br /&gt;
void initialize() {&lt;br /&gt;
   &lt;br /&gt;
   delay_ms(1000);       //Give enough time for the user to release the &amp;quot;reset&amp;quot; button     &lt;br /&gt;
   &lt;br /&gt;
   valueinit=0;&lt;br /&gt;
   &lt;br /&gt;
   //Read 100 input levels and take their average. This a measure of the ambient noise&lt;br /&gt;
   for (k=0;k&amp;lt;100;k++) &lt;br /&gt;
   {&lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      valueinit+=read_adc();&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   valueinit = (valueinit/100);&lt;br /&gt;
   &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
1. [http://en.wikipedia.org/wiki/Microphone Microphone - From Wikipedia, the free encyclopedia] &amp;lt;br&amp;gt;&lt;br /&gt;
2. [http://www.national.com/nationaledge/dec02/article.html Integrated Circuits for High Performance Electret Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
3. [http://www.soundonsound.com/sos/1995_articles/jun95/microphones.html CHOOSING A MICROPHONE: Microphone types and uses] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
[http://www.hosiden.co.jp/web/english/web/products/pdf/e_on06_mic.pdf Guide for Electret Condenser Microphones]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7025</id>
		<title>Microphones</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=7025"/>
		<updated>2008-02-19T22:43:37Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
This project is to demonstrate a &amp;quot;clapper&amp;quot; device using an electret microphone (e.g., the 423-1024-ND from digikey).  Build an appropriate circuit and write a program to continuously display the volume of the sound it receives as a &amp;quot;light bar&amp;quot; on the PIC board LEDs.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;clapper&amp;quot; device will be built using a PIC 18F4520 and an [http://en.wikipedia.org/wiki/Electret_microphone electret microphone] (in this case, the [http://www.knowles.com/search/prods_pdf/MD9745APA-1.pdf 423-1024-ND] from digikey) as an analog input. The device operates on the principle that the microphone will convert the sound into an analog input to the PIC and as the sound increases in volume, the analog input&amp;#039;s amplitude will increase. This input is then converted into an output on the set of LEDs soldered onto the PIC&amp;#039;s circuit board. This output works as a light bar; it displays the minimum one LED for quiet sound levels and activates additional LEDs as the sound becomes louder -- up to a maximum of eight.  The sensitivity of the microphone is adjustable through a gain potentiometer. &lt;br /&gt;
&lt;br /&gt;
[[image:ElectretMicrophone.gif|right|350px|[[help:contents|Interior of Electret Microphone]]]]&lt;br /&gt;
&lt;br /&gt;
Electret microphones work &lt;br /&gt;
&lt;br /&gt;
Due to the variable nature of ambient noise, a calibration &amp;quot;reset&amp;quot; button was included that would reset the output LEDs based on the environment&amp;#039;s baseline noise level. This calibration was done via software averaging of the ambient volume level. The device that is built currently follows the principles of the &amp;quot;clapper&amp;quot; device in that the higher the analog input is received, the more LEDs will be shown. However, due to the brevity of the audio input peak for shorter signals such as a clap, it is sometimes difficult to see the correspondingly brief output.  A further step would be to install a software switch that would detect the characteristic sound pattern of a clap and activate a digital output upon recognition.&lt;br /&gt;
&lt;br /&gt;
Of the three microphones tested (Electret Microphone, [http://www.sonystyle.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=10551&amp;amp;storeId=10151&amp;amp;langId=-1&amp;amp;productId=11037550 Sony F-V100], and a small dynamic microphone), the electret microphone showed the greatest sensitivity to varying noise levels.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
The circuit built for this example uses an electret microphone to listen to external sound and displays the volume level as a light bar on the PIC board LEDs.  The microphone uses a single analog input pin of the PIC.&lt;br /&gt;
&lt;br /&gt;
Optional features present in the shown circuit diagram include a potentiometer gain knob for adjusting the microphone&amp;#039;s sensitivity and a calibration button for setting the baseline ambient noise level.  The code governing the operation of the calibration button is included below; the button itself is wired into a digital input of the PIC. Refer to the photo and diagram for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:400px-Microphone_circuit.JPG|left|400px|[[help:contents|Microphone Circuit and PIC photo]]]] [[image:Mic_circuit_diagram4.JPG|right|350px|[[help:contents|Microphone Circuit and PIC diagram]]]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
microphone.c by JJ Darling, Alex Leung, Ben Schriesheim&lt;br /&gt;
This code will take an analog microphone input and display the power of the single &lt;br /&gt;
as an easily read LED array. One light on means the input matches the ambient noise,&lt;br /&gt;
and all eight lights on means the microphone is receiving a loud noise.&lt;br /&gt;
&lt;br /&gt;
The reset button can be used to match the lowest output to the ambient noise.&lt;br /&gt;
&lt;br /&gt;
This code was derived off of the analog input code written by Prof. Michael Peshkin, which&lt;br /&gt;
can be found in the source code repository on this wiki.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#DEVICE ADC=8                  // set ADC to 8 bit accuracy.&lt;br /&gt;
&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
signed int16 value;&lt;br /&gt;
int16 valueinit=0;&lt;br /&gt;
int k=0;&lt;br /&gt;
void initialize();&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_adc_ports(AN0);        // Enable analog inputs AN0;&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);     &lt;br /&gt;
   initialize(); &lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
   &lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      &lt;br /&gt;
      if (input(PIN_C0)&amp;gt;0)  initialize();   //Initialize the base output to match ambient noise&lt;br /&gt;
      &lt;br /&gt;
      value = read_adc();     // now you can read ADC as frequently as you like&lt;br /&gt;
      &lt;br /&gt;
      //Create a gain to dramatically differentiate the input level from ambient noise&lt;br /&gt;
      if ((value-valueinit)&amp;lt;0) value=0;   &lt;br /&gt;
      value=(value-valueinit)*20;&lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;lt;32)              //Easy to read volume meter&lt;br /&gt;
      output_d(0b1);&lt;br /&gt;
   else if (value&amp;lt;64)&lt;br /&gt;
      output_d(0b11);&lt;br /&gt;
   else if (value&amp;lt;96)&lt;br /&gt;
      output_d(0b111);&lt;br /&gt;
   else if (value&amp;lt;128)&lt;br /&gt;
      output_d(0b1111);&lt;br /&gt;
   else if (value&amp;lt;160)&lt;br /&gt;
      output_d(0b11111);&lt;br /&gt;
   else if (value&amp;lt;192)&lt;br /&gt;
      output_d(0b111111);&lt;br /&gt;
   else if (value&amp;lt;224)&lt;br /&gt;
      output_d(0b1111111);&lt;br /&gt;
   else&lt;br /&gt;
      output_d(0b11111111);           &lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;gt;128) delay_ms(200);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Take samples to establish an initial value to &amp;#039;tare&amp;#039; the ambient noise.&lt;br /&gt;
void initialize() {&lt;br /&gt;
   &lt;br /&gt;
   delay_ms(1000);       //Give enough time for the user to release the &amp;quot;reset&amp;quot; button     &lt;br /&gt;
   &lt;br /&gt;
   valueinit=0;&lt;br /&gt;
   &lt;br /&gt;
   //Read 100 input levels and take their average. This a measure of the ambient noise&lt;br /&gt;
   for (k=0;k&amp;lt;100;k++) &lt;br /&gt;
   {&lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      valueinit+=read_adc();&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   valueinit = (valueinit/100);&lt;br /&gt;
   &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
1. [http://en.wikipedia.org/wiki/Microphone Microphone - From Wikipedia, the free encyclopedia] &amp;lt;br&amp;gt;&lt;br /&gt;
2. [http://www.national.com/nationaledge/dec02/article.html Integrated Circuits for High Performance Electret Microphones] &amp;lt;br&amp;gt;&lt;br /&gt;
3. [http://www.soundonsound.com/sos/1995_articles/jun95/microphones.html CHOOSING A MICROPHONE: Microphone types and uses] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
[http://www.hosiden.co.jp/web/english/web/products/pdf/e_on06_mic.pdf Guide for Electret Condenser Microphones]&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Mic_circuit_diagram4.JPG&amp;diff=7022</id>
		<title>File:Mic circuit diagram4.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Mic_circuit_diagram4.JPG&amp;diff=7022"/>
		<updated>2008-02-19T22:39:53Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=6889</id>
		<title>Microphones</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Microphones&amp;diff=6889"/>
		<updated>2008-02-10T20:33:58Z</updated>

		<summary type="html">&lt;p&gt;JeremyDarling: /* Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
This project is to demonstrate a &amp;quot;clapper&amp;quot; device using an electret microphone (e.g., the 423-1024-ND from digikey).  Build an appropriate circuit and write a program to continuously display the volume of the sound it receives as a &amp;quot;light bar&amp;quot; on the PIC board LEDs.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;clapper&amp;quot; device will be built using a PIC 18F4520 and an electret microphone (in this case, the [http://www.knowles.com/search/prods_pdf/MD9745APA-1.pdf 423-1024-ND] from digikey) as an analog input. The device operates on the principle that the microphone will convert the sound into an analog input to the PIC and as the sound increases in volume, the analog input&amp;#039;s amplitude will increase. This input is then converted into an output on the set of LEDs soldered onto the PIC&amp;#039;s circuit board. This output works as a light bar; it displays the minimum one LED for quiet sound levels and activates additional LEDs as the sound becomes louder -- up to a maximum of eight.  The sensitivity of the microphone is adjustable through a gain potentiometer. &lt;br /&gt;
&lt;br /&gt;
Due to the variable nature of ambient noise, a calibration &amp;quot;reset&amp;quot; button was included that would reset the output LEDs based on the environment&amp;#039;s baseline noise level. This calibration was done via software averaging of the ambient volume level. The device that is built currently follows the principles of the &amp;quot;clapper&amp;quot; device in that the higher the analog input is received, the more LEDs will be shown. However, due to the brevity of the audio input peak for shorter signals such as a clap, it is sometimes difficult to see the correspondingly brief output.  A further step would be to install a software switch that would detect the characteristic sound pattern of a clap and activate a digital output upon recognition.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
The circuit built for this example uses an electret microphone to listen to external sound and displays the volume level as a light bar on the PIC board LEDs.  The microphone uses a single analog input pin of the PIC.&lt;br /&gt;
&lt;br /&gt;
Optional features present in the shown circuit diagram include a potentiometer gain knob for adjusting the microphone&amp;#039;s sensitivity and a calibration button for setting the baseline ambient noise level.  The code governing the operation of the calibration button is included below; the button itself is wired into a digital input of the PIC. Refer to the photo and diagram for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[image:400px-Microphone_circuit.JPG|left|400px|[[help:contents|Microphone Circuit and PIC photo]]]] [[image:Mic_circuit_diagram2.JPG|right|350px|[[help:contents|Microphone Circuit and PIC diagram]]]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
microphone.c by JJ Darling, Alex Leung, Ben Schriesheim&lt;br /&gt;
This code will take an analog microphone input and display the power of the single &lt;br /&gt;
as an easily read LED array. One light on means the input matches the ambient noise,&lt;br /&gt;
and all eight lights on means the microphone is receiving a loud noise.&lt;br /&gt;
&lt;br /&gt;
The reset button can be used to match the lowest output to the ambient noise.&lt;br /&gt;
&lt;br /&gt;
This code was derived off of the analog input code written by Prof. Michael Peshkin, which&lt;br /&gt;
can be found in the source code repository on this wiki.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#DEVICE ADC=8                  // set ADC to 8 bit accuracy.&lt;br /&gt;
&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=20000000)&lt;br /&gt;
&lt;br /&gt;
int16 valuebuff[100];      // Initialize variables&lt;br /&gt;
signed int16 value;&lt;br /&gt;
int32 valueinit=0;&lt;br /&gt;
int k=0;&lt;br /&gt;
void initialize();&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
   initialize(); &lt;br /&gt;
   setup_adc_ports(AN0);        // Enable analog inputs AN0;&lt;br /&gt;
   setup_adc(ADC_CLOCK_INTERNAL);      &lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {&lt;br /&gt;
      if (input(PIN_C0)&amp;gt;0)  initialize();   //Initialize the base output to match ambient noise&lt;br /&gt;
&lt;br /&gt;
      set_adc_channel(0);     // there&amp;#039;s only one ADC so select which input to connect to it; here pin AN0&lt;br /&gt;
      delay_us(10);           // wait 10uS for ADC to settle to a newly selected input&lt;br /&gt;
      value = read_adc();     // now you can read ADC as frequently as you like&lt;br /&gt;
      &lt;br /&gt;
      //Create a gain to dramatically differentiate the input level from ambient noise&lt;br /&gt;
      if ((value-valueinit)&amp;lt;0) value=0;   &lt;br /&gt;
      value=(value-valueinit)*4;&lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;lt;32)              //Easy to read volume meter&lt;br /&gt;
      output_d(0b1);&lt;br /&gt;
   else if (value&amp;lt;64)&lt;br /&gt;
      output_d(0b11);&lt;br /&gt;
   else if (value&amp;lt;96)&lt;br /&gt;
      output_d(0b111);&lt;br /&gt;
   else if (value&amp;lt;128)&lt;br /&gt;
      output_d(0b1111);&lt;br /&gt;
   else if (value&amp;lt;160)&lt;br /&gt;
      output_d(0b11111);&lt;br /&gt;
   else if (value&amp;lt;192)&lt;br /&gt;
      output_d(0b111111);&lt;br /&gt;
   else if (value&amp;lt;224)&lt;br /&gt;
      output_d(0b1111111);&lt;br /&gt;
   else if (value&amp;lt;1000)&lt;br /&gt;
      output_d(0b11111111);           &lt;br /&gt;
      &lt;br /&gt;
   if (value&amp;gt;128) delay_ms(500);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Take samples to establish an initial value to &amp;#039;tare&amp;#039; the ambient noise.&lt;br /&gt;
void initialize() {&lt;br /&gt;
   &lt;br /&gt;
   delay_ms(1000);       //Give enough time for the user to release the &amp;quot;reset&amp;quot; button     &lt;br /&gt;
   &lt;br /&gt;
   valueinit=0;&lt;br /&gt;
   &lt;br /&gt;
   //Read 100 input levels and take their average. This a measure of the ambient noise&lt;br /&gt;
   for (k=0;k&amp;lt;100;k++) {&lt;br /&gt;
      set_adc_channel(0);     &lt;br /&gt;
      delay_us(10);           &lt;br /&gt;
      valuebuff[k] = read_adc();    &lt;br /&gt;
      valueinit+=valuebuff[k];&lt;br /&gt;
   }&lt;br /&gt;
   valueinit = (valueinit/100);&lt;br /&gt;
   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>JeremyDarling</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:400px-Microphone_circuit.JPG&amp;diff=6888</id>
		<title>File:400px-Microphone circuit.JPG</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:400px-Microphone_circuit.JPG&amp;diff=6888"/>
		<updated>2008-02-10T20:32:09Z</updated>

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