<?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=John+Rula</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=John+Rula"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php/Special:Contributions/John_Rula"/>
	<updated>2026-04-29T10:00:17Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.9</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13624</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13624"/>
		<updated>2009-07-03T21:00:16Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* MATLAB Motor Controller */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MATLAB Motor Controller=&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. The idea is to have the ability to tune your motor controller through a MATLAB GUI interface by changing the proportional and derivative gain constants. In this premise, the slave PIC controls the high speed motor with quadrature encoding. The slave PICs used are the 18f4431 since they have a built in quadrature encoder. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The slave PICs are controlled via I2C by the master PIC which is an 18f4520. The master PIC is controlled through MATLAB over RS-232. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;br /&gt;
&lt;br /&gt;
[[Image:JR-matlab-gui2.jpg | right | 800px]]&lt;br /&gt;
==SRAM Memory==&lt;br /&gt;
===SPI SRAM===&lt;br /&gt;
The project originally was going to use SPI SRAM from Microchip since you can find capacities around 256kbit with only 4 connections. Unfortunately I was unable to get this memory to work with the 5V PICS I was using. I tested the Microchip 23A256 and Winbound SPI SRAM chips. Neither of these chips run at 5V, the Microchip SRAM runs at 1.8V and the Winbound chip runs at 3.3V. I tried voltage dividers, diode drops and pull-ups with diodes and was unsuccessful at communicating with the SRAM chips.For communicating through SPI, there are several other pages on the wiki which discuss it more in detail.&lt;br /&gt;
===Parallel SRAM===&lt;br /&gt;
I instead used parallel memory in the final design, with the only downside that this memory requires 26 dedicated pins from the PIC (15 for address, 8 for data I/O and 3 for control). I wrote a small library for communicating with parallel memory located [here]. Notice that since so many pins are required, they will most likely always be different, so the pins are listed in order in arrays data_pins[] and address_pins[]. The parallel ram functions can be found here.  [[Media:Parallel_Mem.h | Parallel_Mem.h]]&lt;br /&gt;
==Code==&lt;br /&gt;
The code for the project can be found here.&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Master.c | Motor Control Master]]&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Slave.c | Motor Control Slave]]&lt;br /&gt;
&lt;br /&gt;
===Master PIC===&lt;br /&gt;
The Master PIC receives commands from MATLAB over RS232 and relays them to the slave over I2C. There are numerous articles in this wiki describing both RS232 between MATLAB and I2C communications.&lt;br /&gt;
&lt;br /&gt;
On the 18F4520 PIC, the hardware buffer for RS232 is only 3 characters long, and if that overflows, the RS232 communication shuts down. I found it necessary to implement an additional software buffer which pulled the characters from the RS232 interrupt and placed them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  #define rs_kbhit              (rs_nextIn != rs_nextOut)&lt;br /&gt;
&lt;br /&gt;
Which is analogous to the kbhit() function and returns true if there are new characters in the buffer.&lt;br /&gt;
&lt;br /&gt;
  #INT_RDA&lt;br /&gt;
  void rda_isr() {&lt;br /&gt;
     //fired when character is loaded into rs232 buffer (only 3 characters long)&lt;br /&gt;
     if(kbhit()) {&lt;br /&gt;
        //wait for buffer inputs&lt;br /&gt;
        //Load character into software rs232 buffer&lt;br /&gt;
        rsBuffer[rs_nextIn] = getc();&lt;br /&gt;
        rs_nextIn++;&lt;br /&gt;
        if(rs_nextIn&amp;gt;=RS232_BUFFER_SIZE) rs_nextIn = 0;&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The RS232 Interrupt pulls the characters from the hardware buffer and places them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  int8 rs_getc() {&lt;br /&gt;
     int8 c;&lt;br /&gt;
   &lt;br /&gt;
     while(!rs_kbhit);&lt;br /&gt;
     c = rsBuffer[rs_nextOut];&lt;br /&gt;
     rs_nextOut++;&lt;br /&gt;
     if(rs_nextOut &amp;gt; RS232_BUFFER_SIZE) rs_nextOut=0;&lt;br /&gt;
   &lt;br /&gt;
     return c;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
This function is to be used in the place of get_c().&lt;br /&gt;
&lt;br /&gt;
For the forwarding of MATLAB commands, the values sent through RS232 are put through a large switch to process them.&lt;br /&gt;
&lt;br /&gt;
===Slave PIC===&lt;br /&gt;
The Slave PIC used is an 18F4431 which has a quadrature encoder built in. Details on the 4431 can be found on the Robot Drummer project page. The commands sent from the Master PIC are processed in the SSP Interrupt so the PIC knows which values to get or set. The set commands are triggered through a dummy slave send command.&lt;br /&gt;
&lt;br /&gt;
  #INT_SSP high&lt;br /&gt;
  void ssp_isr() {&lt;br /&gt;
   disable_interrupts(GLOBAL);&lt;br /&gt;
   state = i2c_isr_state();&lt;br /&gt;
   if(state &amp;lt; 0x80)                 //master is sending data&lt;br /&gt;
   {&lt;br /&gt;
      if(state == 0)&lt;br /&gt;
      {&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
      if(state == 1)                   //second received byte is command&lt;br /&gt;
      {&lt;br /&gt;
         command = i2c_read();&lt;br /&gt;
         bitCount=0;&lt;br /&gt;
      }&lt;br /&gt;
      if(state &amp;gt;= 2 &amp;amp;&amp;amp; state &amp;lt; 6)                   //other received bytes are data bytes&lt;br /&gt;
      {&lt;br /&gt;
         numBuf[state-2] = i2c_read();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   //have to do when state==0x80 since sending from slave gets buggy when more than one&lt;br /&gt;
   //state is used and cannot be state &amp;gt;= 0x80 since stop bit triggers a state increment&lt;br /&gt;
   if(state == 0x80)                //master is requesting data&lt;br /&gt;
   {&lt;br /&gt;
      switch(command) {&lt;br /&gt;
         case MC_GET_VELOCITY:&lt;br /&gt;
            i2c_write((int8)(vel_act&amp;gt;&amp;gt;(bitCount*8)));&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
      bitCount++;&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The Slave PIC also implements a PD controller.&lt;br /&gt;
&lt;br /&gt;
  // Proportional Derivative Control&lt;br /&gt;
  void PID()                                           &lt;br /&gt;
  {&lt;br /&gt;
   updateStatus();&lt;br /&gt;
  &lt;br /&gt;
   velocity_count += vel_act;&lt;br /&gt;
   if(velocity_count &amp;lt; 0) {&lt;br /&gt;
      TargetPosition -= (velocity_count&amp;amp; 0x7FFFFFFF);      //negative velocity, need to convert to unsigned and subtract&lt;br /&gt;
      velocity_count = velocity_count &amp;amp; 0x800000FF;&lt;br /&gt;
   } else {&lt;br /&gt;
      TargetPosition += velocity_count;&lt;br /&gt;
      velocity_count = velocity_count &amp;amp; 0xFF;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   &lt;br /&gt;
   error = (signed int32) ((signed int32) TargetPosition - (signed int32) TotalCount);             // Compute proportional error&lt;br /&gt;
   derivative = error - last_error;                           // Compute Derivative Error&lt;br /&gt;
   last_error = error;&lt;br /&gt;
   &lt;br /&gt;
   duty = 1000;                                       // Set Duty to 50%&lt;br /&gt;
   duty += kp*error + kd*derivative;                  // Adjust Duty of motor (wrt to error)&lt;br /&gt;
   &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
   if (duty &amp;gt; 1990)                                   // Check for Saturation&lt;br /&gt;
   {&lt;br /&gt;
      duty = 1990;&lt;br /&gt;
   }&lt;br /&gt;
   else if (duty &amp;lt; 10)&lt;br /&gt;
   {&lt;br /&gt;
      duty = 10;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   if(go == 1) {&lt;br /&gt;
     //record data&lt;br /&gt;
     if(dataCount &amp;lt; MEM_SIZE) {&lt;br /&gt;
        if((timeCount % timeInterval) == 0 ) {&lt;br /&gt;
           motorData[dataCount][0] = TargetPosition;&lt;br /&gt;
           motorData[dataCount][1] = TotalCount;&lt;br /&gt;
           dataCount++;&lt;br /&gt;
           output_d(dataCount);&lt;br /&gt;
        }&lt;br /&gt;
     } else {&lt;br /&gt;
        go = 0;&lt;br /&gt;
     }&lt;br /&gt;
   } else {&lt;br /&gt;
      duty = 1000;&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   disable_interrupts(GLOBAL);&lt;br /&gt;
   set_power_pwm0_duty((int16)duty);                  // Adjust PWM in response to PID control&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   &lt;br /&gt;
   timeCount++;&lt;br /&gt;
   &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The gains kp and kd are settable through MATLAB as you can tune your motor controller through the MATLAB interface. The variable &amp;#039;go&amp;#039; is used to tell the motor when to start motor operations, it also stops the motor when the correct amount of tracking data has been collected. The motor data is also stored in the PID() function. Since the PID fires every 400us, the variable timeInterval is used to break the collection into larger time chunks.&lt;br /&gt;
&lt;br /&gt;
==MATLAB GUI Programming==&lt;br /&gt;
[[Media:motor_controller.m | motor_controller.m]]&lt;br /&gt;
&lt;br /&gt;
The GUI for the controller is programmed through the GUIde feature of MATLAB. The code for the GUI is contained [here]. The difference between normal MATLAB programming and GUI programming is that there are no global variables for storing values that are easily creatable or accessible. If you want to access data from a GUI component, you have to through the &amp;#039;handles&amp;#039; structure, which is a structure containing all of the GUI components on your form. In order to access a string in a text-box, it has to be retrieved in the following manner:&lt;br /&gt;
  str = get(handles.textbox-1, &amp;#039;String&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
Also note that in GUI programming, every component has a Callback, which is called when an action is performed on a component (ie a button is pushed). Within the callback, three things are passed, the object itself called &amp;#039;hobject&amp;#039;, &amp;#039;eventData&amp;#039; which does nothing, and the &amp;#039;handles&amp;#039; structure. Utilizing callbacks are how you are able to perform actions based on interaction.&lt;br /&gt;
&lt;br /&gt;
If you want to store variables that you want to either access at a later time, or have variables that you can only create once (ie serial ports), then you have to store them in the application data structure. Application data can be placed and accessed in the following way:&lt;br /&gt;
  setappdata(hObject, &amp;#039;serialport&amp;#039;, sp)&lt;br /&gt;
  sp = getappdata(handles.pushbutton1, &amp;#039;serialport&amp;#039;)&lt;br /&gt;
where &amp;#039;serialport&amp;#039; is the name give in the structure, and sp is what you are storing, in this case an open serial port. Also note that since the application data was stored under pushbutton1, it has to always be accessed through that same component.&lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
I was never able to implement the external SRAM to store motor values, and in the end had to store them internally which limited me to only 65 data points due to memory constraints. I would suggest in the future to try this project with an 18FXXJXX series PIC since they run at a native voltage of 3.3V and would have an easier time talking to the lower voltage SRAM chips.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13623</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13623"/>
		<updated>2009-07-03T20:57:46Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* MATLAB GUI Programming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MATLAB Motor Controller=&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. In this premise, the slave PIC controls the high speed motor with quadrature encoding. The slave PICs used are the 18f4431 since they have a built in quadrature encoder. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The slave PICs are controlled via I2C by the master PIC which is an 18f4520. The master PIC is controlled through MATLAB over RS-232. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;br /&gt;
&lt;br /&gt;
[[Image:JR-matlab-gui2.jpg | right | 800px]]&lt;br /&gt;
==SRAM Memory==&lt;br /&gt;
===SPI SRAM===&lt;br /&gt;
The project originally was going to use SPI SRAM from Microchip since you can find capacities around 256kbit with only 4 connections. Unfortunately I was unable to get this memory to work with the 5V PICS I was using. I tested the Microchip 23A256 and Winbound SPI SRAM chips. Neither of these chips run at 5V, the Microchip SRAM runs at 1.8V and the Winbound chip runs at 3.3V. I tried voltage dividers, diode drops and pull-ups with diodes and was unsuccessful at communicating with the SRAM chips.For communicating through SPI, there are several other pages on the wiki which discuss it more in detail.&lt;br /&gt;
===Parallel SRAM===&lt;br /&gt;
I instead used parallel memory in the final design, with the only downside that this memory requires 26 dedicated pins from the PIC (15 for address, 8 for data I/O and 3 for control). I wrote a small library for communicating with parallel memory located [here]. Notice that since so many pins are required, they will most likely always be different, so the pins are listed in order in arrays data_pins[] and address_pins[]. The parallel ram functions can be found here.  [[Media:Parallel_Mem.h | Parallel_Mem.h]]&lt;br /&gt;
==Code==&lt;br /&gt;
The code for the project can be found here.&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Master.c | Motor Control Master]]&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Slave.c | Motor Control Slave]]&lt;br /&gt;
&lt;br /&gt;
===Master PIC===&lt;br /&gt;
The Master PIC receives commands from MATLAB over RS232 and relays them to the slave over I2C. There are numerous articles in this wiki describing both RS232 between MATLAB and I2C communications.&lt;br /&gt;
&lt;br /&gt;
On the 18F4520 PIC, the hardware buffer for RS232 is only 3 characters long, and if that overflows, the RS232 communication shuts down. I found it necessary to implement an additional software buffer which pulled the characters from the RS232 interrupt and placed them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  #define rs_kbhit              (rs_nextIn != rs_nextOut)&lt;br /&gt;
&lt;br /&gt;
Which is analogous to the kbhit() function and returns true if there are new characters in the buffer.&lt;br /&gt;
&lt;br /&gt;
  #INT_RDA&lt;br /&gt;
  void rda_isr() {&lt;br /&gt;
     //fired when character is loaded into rs232 buffer (only 3 characters long)&lt;br /&gt;
     if(kbhit()) {&lt;br /&gt;
        //wait for buffer inputs&lt;br /&gt;
        //Load character into software rs232 buffer&lt;br /&gt;
        rsBuffer[rs_nextIn] = getc();&lt;br /&gt;
        rs_nextIn++;&lt;br /&gt;
        if(rs_nextIn&amp;gt;=RS232_BUFFER_SIZE) rs_nextIn = 0;&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The RS232 Interrupt pulls the characters from the hardware buffer and places them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  int8 rs_getc() {&lt;br /&gt;
     int8 c;&lt;br /&gt;
   &lt;br /&gt;
     while(!rs_kbhit);&lt;br /&gt;
     c = rsBuffer[rs_nextOut];&lt;br /&gt;
     rs_nextOut++;&lt;br /&gt;
     if(rs_nextOut &amp;gt; RS232_BUFFER_SIZE) rs_nextOut=0;&lt;br /&gt;
   &lt;br /&gt;
     return c;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
This function is to be used in the place of get_c().&lt;br /&gt;
&lt;br /&gt;
For the forwarding of MATLAB commands, the values sent through RS232 are put through a large switch to process them.&lt;br /&gt;
&lt;br /&gt;
===Slave PIC===&lt;br /&gt;
The Slave PIC used is an 18F4431 which has a quadrature encoder built in. Details on the 4431 can be found on the Robot Drummer project page. The commands sent from the Master PIC are processed in the SSP Interrupt so the PIC knows which values to get or set. The set commands are triggered through a dummy slave send command.&lt;br /&gt;
&lt;br /&gt;
  #INT_SSP high&lt;br /&gt;
  void ssp_isr() {&lt;br /&gt;
   disable_interrupts(GLOBAL);&lt;br /&gt;
   state = i2c_isr_state();&lt;br /&gt;
   if(state &amp;lt; 0x80)                 //master is sending data&lt;br /&gt;
   {&lt;br /&gt;
      if(state == 0)&lt;br /&gt;
      {&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
      if(state == 1)                   //second received byte is command&lt;br /&gt;
      {&lt;br /&gt;
         command = i2c_read();&lt;br /&gt;
         bitCount=0;&lt;br /&gt;
      }&lt;br /&gt;
      if(state &amp;gt;= 2 &amp;amp;&amp;amp; state &amp;lt; 6)                   //other received bytes are data bytes&lt;br /&gt;
      {&lt;br /&gt;
         numBuf[state-2] = i2c_read();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   //have to do when state==0x80 since sending from slave gets buggy when more than one&lt;br /&gt;
   //state is used and cannot be state &amp;gt;= 0x80 since stop bit triggers a state increment&lt;br /&gt;
   if(state == 0x80)                //master is requesting data&lt;br /&gt;
   {&lt;br /&gt;
      switch(command) {&lt;br /&gt;
         case MC_GET_VELOCITY:&lt;br /&gt;
            i2c_write((int8)(vel_act&amp;gt;&amp;gt;(bitCount*8)));&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
      bitCount++;&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The Slave PIC also implements a PD controller.&lt;br /&gt;
&lt;br /&gt;
  // Proportional Derivative Control&lt;br /&gt;
  void PID()                                           &lt;br /&gt;
  {&lt;br /&gt;
   updateStatus();&lt;br /&gt;
  &lt;br /&gt;
   velocity_count += vel_act;&lt;br /&gt;
   if(velocity_count &amp;lt; 0) {&lt;br /&gt;
      TargetPosition -= (velocity_count&amp;amp; 0x7FFFFFFF);      //negative velocity, need to convert to unsigned and subtract&lt;br /&gt;
      velocity_count = velocity_count &amp;amp; 0x800000FF;&lt;br /&gt;
   } else {&lt;br /&gt;
      TargetPosition += velocity_count;&lt;br /&gt;
      velocity_count = velocity_count &amp;amp; 0xFF;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   &lt;br /&gt;
   error = (signed int32) ((signed int32) TargetPosition - (signed int32) TotalCount);             // Compute proportional error&lt;br /&gt;
   derivative = error - last_error;                           // Compute Derivative Error&lt;br /&gt;
   last_error = error;&lt;br /&gt;
   &lt;br /&gt;
   duty = 1000;                                       // Set Duty to 50%&lt;br /&gt;
   duty += kp*error + kd*derivative;                  // Adjust Duty of motor (wrt to error)&lt;br /&gt;
   &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
   if (duty &amp;gt; 1990)                                   // Check for Saturation&lt;br /&gt;
   {&lt;br /&gt;
      duty = 1990;&lt;br /&gt;
   }&lt;br /&gt;
   else if (duty &amp;lt; 10)&lt;br /&gt;
   {&lt;br /&gt;
      duty = 10;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   if(go == 1) {&lt;br /&gt;
     //record data&lt;br /&gt;
     if(dataCount &amp;lt; MEM_SIZE) {&lt;br /&gt;
        if((timeCount % timeInterval) == 0 ) {&lt;br /&gt;
           motorData[dataCount][0] = TargetPosition;&lt;br /&gt;
           motorData[dataCount][1] = TotalCount;&lt;br /&gt;
           dataCount++;&lt;br /&gt;
           output_d(dataCount);&lt;br /&gt;
        }&lt;br /&gt;
     } else {&lt;br /&gt;
        go = 0;&lt;br /&gt;
     }&lt;br /&gt;
   } else {&lt;br /&gt;
      duty = 1000;&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   disable_interrupts(GLOBAL);&lt;br /&gt;
   set_power_pwm0_duty((int16)duty);                  // Adjust PWM in response to PID control&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   &lt;br /&gt;
   timeCount++;&lt;br /&gt;
   &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The gains kp and kd are settable through MATLAB as you can tune your motor controller through the MATLAB interface. The variable &amp;#039;go&amp;#039; is used to tell the motor when to start motor operations, it also stops the motor when the correct amount of tracking data has been collected. The motor data is also stored in the PID() function. Since the PID fires every 400us, the variable timeInterval is used to break the collection into larger time chunks.&lt;br /&gt;
&lt;br /&gt;
==MATLAB GUI Programming==&lt;br /&gt;
[[Media:motor_controller.m | motor_controller.m]]&lt;br /&gt;
&lt;br /&gt;
The GUI for the controller is programmed through the GUIde feature of MATLAB. The code for the GUI is contained [here]. The difference between normal MATLAB programming and GUI programming is that there are no global variables for storing values that are easily creatable or accessible. If you want to access data from a GUI component, you have to through the &amp;#039;handles&amp;#039; structure, which is a structure containing all of the GUI components on your form. In order to access a string in a text-box, it has to be retrieved in the following manner:&lt;br /&gt;
  str = get(handles.textbox-1, &amp;#039;String&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
Also note that in GUI programming, every component has a Callback, which is called when an action is performed on a component (ie a button is pushed). Within the callback, three things are passed, the object itself called &amp;#039;hobject&amp;#039;, &amp;#039;eventData&amp;#039; which does nothing, and the &amp;#039;handles&amp;#039; structure. Utilizing callbacks are how you are able to perform actions based on interaction.&lt;br /&gt;
&lt;br /&gt;
If you want to store variables that you want to either access at a later time, or have variables that you can only create once (ie serial ports), then you have to store them in the application data structure. Application data can be placed and accessed in the following way:&lt;br /&gt;
  setappdata(hObject, &amp;#039;serialport&amp;#039;, sp)&lt;br /&gt;
  sp = getappdata(handles.pushbutton1, &amp;#039;serialport&amp;#039;)&lt;br /&gt;
where &amp;#039;serialport&amp;#039; is the name give in the structure, and sp is what you are storing, in this case an open serial port. Also note that since the application data was stored under pushbutton1, it has to always be accessed through that same component.&lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
I was never able to implement the external SRAM to store motor values, and in the end had to store them internally which limited me to only 65 data points due to memory constraints. I would suggest in the future to try this project with an 18FXXJXX series PIC since they run at a native voltage of 3.3V and would have an easier time talking to the lower voltage SRAM chips.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13622</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13622"/>
		<updated>2009-07-03T20:56:45Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MATLAB Motor Controller=&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. In this premise, the slave PIC controls the high speed motor with quadrature encoding. The slave PICs used are the 18f4431 since they have a built in quadrature encoder. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The slave PICs are controlled via I2C by the master PIC which is an 18f4520. The master PIC is controlled through MATLAB over RS-232. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;br /&gt;
&lt;br /&gt;
[[Image:JR-matlab-gui2.jpg | right | 800px]]&lt;br /&gt;
==SRAM Memory==&lt;br /&gt;
===SPI SRAM===&lt;br /&gt;
The project originally was going to use SPI SRAM from Microchip since you can find capacities around 256kbit with only 4 connections. Unfortunately I was unable to get this memory to work with the 5V PICS I was using. I tested the Microchip 23A256 and Winbound SPI SRAM chips. Neither of these chips run at 5V, the Microchip SRAM runs at 1.8V and the Winbound chip runs at 3.3V. I tried voltage dividers, diode drops and pull-ups with diodes and was unsuccessful at communicating with the SRAM chips.For communicating through SPI, there are several other pages on the wiki which discuss it more in detail.&lt;br /&gt;
===Parallel SRAM===&lt;br /&gt;
I instead used parallel memory in the final design, with the only downside that this memory requires 26 dedicated pins from the PIC (15 for address, 8 for data I/O and 3 for control). I wrote a small library for communicating with parallel memory located [here]. Notice that since so many pins are required, they will most likely always be different, so the pins are listed in order in arrays data_pins[] and address_pins[]. The parallel ram functions can be found here.  [[Media:Parallel_Mem.h | Parallel_Mem.h]]&lt;br /&gt;
==Code==&lt;br /&gt;
The code for the project can be found here.&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Master.c | Motor Control Master]]&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Slave.c | Motor Control Slave]]&lt;br /&gt;
&lt;br /&gt;
===Master PIC===&lt;br /&gt;
The Master PIC receives commands from MATLAB over RS232 and relays them to the slave over I2C. There are numerous articles in this wiki describing both RS232 between MATLAB and I2C communications.&lt;br /&gt;
&lt;br /&gt;
On the 18F4520 PIC, the hardware buffer for RS232 is only 3 characters long, and if that overflows, the RS232 communication shuts down. I found it necessary to implement an additional software buffer which pulled the characters from the RS232 interrupt and placed them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  #define rs_kbhit              (rs_nextIn != rs_nextOut)&lt;br /&gt;
&lt;br /&gt;
Which is analogous to the kbhit() function and returns true if there are new characters in the buffer.&lt;br /&gt;
&lt;br /&gt;
  #INT_RDA&lt;br /&gt;
  void rda_isr() {&lt;br /&gt;
     //fired when character is loaded into rs232 buffer (only 3 characters long)&lt;br /&gt;
     if(kbhit()) {&lt;br /&gt;
        //wait for buffer inputs&lt;br /&gt;
        //Load character into software rs232 buffer&lt;br /&gt;
        rsBuffer[rs_nextIn] = getc();&lt;br /&gt;
        rs_nextIn++;&lt;br /&gt;
        if(rs_nextIn&amp;gt;=RS232_BUFFER_SIZE) rs_nextIn = 0;&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The RS232 Interrupt pulls the characters from the hardware buffer and places them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  int8 rs_getc() {&lt;br /&gt;
     int8 c;&lt;br /&gt;
   &lt;br /&gt;
     while(!rs_kbhit);&lt;br /&gt;
     c = rsBuffer[rs_nextOut];&lt;br /&gt;
     rs_nextOut++;&lt;br /&gt;
     if(rs_nextOut &amp;gt; RS232_BUFFER_SIZE) rs_nextOut=0;&lt;br /&gt;
   &lt;br /&gt;
     return c;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
This function is to be used in the place of get_c().&lt;br /&gt;
&lt;br /&gt;
For the forwarding of MATLAB commands, the values sent through RS232 are put through a large switch to process them.&lt;br /&gt;
&lt;br /&gt;
===Slave PIC===&lt;br /&gt;
The Slave PIC used is an 18F4431 which has a quadrature encoder built in. Details on the 4431 can be found on the Robot Drummer project page. The commands sent from the Master PIC are processed in the SSP Interrupt so the PIC knows which values to get or set. The set commands are triggered through a dummy slave send command.&lt;br /&gt;
&lt;br /&gt;
  #INT_SSP high&lt;br /&gt;
  void ssp_isr() {&lt;br /&gt;
   disable_interrupts(GLOBAL);&lt;br /&gt;
   state = i2c_isr_state();&lt;br /&gt;
   if(state &amp;lt; 0x80)                 //master is sending data&lt;br /&gt;
   {&lt;br /&gt;
      if(state == 0)&lt;br /&gt;
      {&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
      if(state == 1)                   //second received byte is command&lt;br /&gt;
      {&lt;br /&gt;
         command = i2c_read();&lt;br /&gt;
         bitCount=0;&lt;br /&gt;
      }&lt;br /&gt;
      if(state &amp;gt;= 2 &amp;amp;&amp;amp; state &amp;lt; 6)                   //other received bytes are data bytes&lt;br /&gt;
      {&lt;br /&gt;
         numBuf[state-2] = i2c_read();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   //have to do when state==0x80 since sending from slave gets buggy when more than one&lt;br /&gt;
   //state is used and cannot be state &amp;gt;= 0x80 since stop bit triggers a state increment&lt;br /&gt;
   if(state == 0x80)                //master is requesting data&lt;br /&gt;
   {&lt;br /&gt;
      switch(command) {&lt;br /&gt;
         case MC_GET_VELOCITY:&lt;br /&gt;
            i2c_write((int8)(vel_act&amp;gt;&amp;gt;(bitCount*8)));&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
      bitCount++;&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The Slave PIC also implements a PD controller.&lt;br /&gt;
&lt;br /&gt;
  // Proportional Derivative Control&lt;br /&gt;
  void PID()                                           &lt;br /&gt;
  {&lt;br /&gt;
   updateStatus();&lt;br /&gt;
  &lt;br /&gt;
   velocity_count += vel_act;&lt;br /&gt;
   if(velocity_count &amp;lt; 0) {&lt;br /&gt;
      TargetPosition -= (velocity_count&amp;amp; 0x7FFFFFFF);      //negative velocity, need to convert to unsigned and subtract&lt;br /&gt;
      velocity_count = velocity_count &amp;amp; 0x800000FF;&lt;br /&gt;
   } else {&lt;br /&gt;
      TargetPosition += velocity_count;&lt;br /&gt;
      velocity_count = velocity_count &amp;amp; 0xFF;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   &lt;br /&gt;
   error = (signed int32) ((signed int32) TargetPosition - (signed int32) TotalCount);             // Compute proportional error&lt;br /&gt;
   derivative = error - last_error;                           // Compute Derivative Error&lt;br /&gt;
   last_error = error;&lt;br /&gt;
   &lt;br /&gt;
   duty = 1000;                                       // Set Duty to 50%&lt;br /&gt;
   duty += kp*error + kd*derivative;                  // Adjust Duty of motor (wrt to error)&lt;br /&gt;
   &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
   if (duty &amp;gt; 1990)                                   // Check for Saturation&lt;br /&gt;
   {&lt;br /&gt;
      duty = 1990;&lt;br /&gt;
   }&lt;br /&gt;
   else if (duty &amp;lt; 10)&lt;br /&gt;
   {&lt;br /&gt;
      duty = 10;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   if(go == 1) {&lt;br /&gt;
     //record data&lt;br /&gt;
     if(dataCount &amp;lt; MEM_SIZE) {&lt;br /&gt;
        if((timeCount % timeInterval) == 0 ) {&lt;br /&gt;
           motorData[dataCount][0] = TargetPosition;&lt;br /&gt;
           motorData[dataCount][1] = TotalCount;&lt;br /&gt;
           dataCount++;&lt;br /&gt;
           output_d(dataCount);&lt;br /&gt;
        }&lt;br /&gt;
     } else {&lt;br /&gt;
        go = 0;&lt;br /&gt;
     }&lt;br /&gt;
   } else {&lt;br /&gt;
      duty = 1000;&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   disable_interrupts(GLOBAL);&lt;br /&gt;
   set_power_pwm0_duty((int16)duty);                  // Adjust PWM in response to PID control&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   &lt;br /&gt;
   timeCount++;&lt;br /&gt;
   &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The gains kp and kd are settable through MATLAB as you can tune your motor controller through the MATLAB interface. The variable &amp;#039;go&amp;#039; is used to tell the motor when to start motor operations, it also stops the motor when the correct amount of tracking data has been collected. The motor data is also stored in the PID() function. Since the PID fires every 400us, the variable timeInterval is used to break the collection into larger time chunks.&lt;br /&gt;
&lt;br /&gt;
==MATLAB GUI Programming==&lt;br /&gt;
The GUI for the controller is programmed through the GUIde feature of MATLAB. The code for the GUI is contained [here]. The difference between normal MATLAB programming and GUI programming is that there are no global variables for storing values that are easily creatable or accessible. If you want to access data from a GUI component, you have to through the &amp;#039;handles&amp;#039; structure, which is a structure containing all of the GUI components on your form. In order to access a string in a text-box, it has to be retrieved in the following manner:&lt;br /&gt;
  str = get(handles.textbox-1, &amp;#039;String&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
Also note that in GUI programming, every component has a Callback, which is called when an action is performed on a component (ie a button is pushed). Within the callback, three things are passed, the object itself called &amp;#039;hobject&amp;#039;, &amp;#039;eventData&amp;#039; which does nothing, and the &amp;#039;handles&amp;#039; structure. Utilizing callbacks are how you are able to perform actions based on interaction.&lt;br /&gt;
&lt;br /&gt;
If you want to store variables that you want to either access at a later time, or have variables that you can only create once (ie serial ports), then you have to store them in the application data structure. Application data can be placed and accessed in the following way:&lt;br /&gt;
  setappdata(hObject, &amp;#039;serialport&amp;#039;, sp)&lt;br /&gt;
  sp = getappdata(handles.pushbutton1, &amp;#039;serialport&amp;#039;)&lt;br /&gt;
where &amp;#039;serialport&amp;#039; is the name give in the structure, and sp is what you are storing, in this case an open serial port. Also note that since the application data was stored under pushbutton1, it has to always be accessed through that same component.&lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
I was never able to implement the external SRAM to store motor values, and in the end had to store them internally which limited me to only 65 data points due to memory constraints. I would suggest in the future to try this project with an 18FXXJXX series PIC since they run at a native voltage of 3.3V and would have an easier time talking to the lower voltage SRAM chips.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13621</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13621"/>
		<updated>2009-07-03T20:52:11Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MATLAB Motor Controller=&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. In this premise, the slave PIC controls the high speed motor with quadrature encoding. The slave PICs used are the 18f4431 since they have a built in quadrature encoder. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The slave PICs are controlled via I2C by the master PIC which is an 18f4520. The master PIC is controlled through MATLAB over RS-232. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;br /&gt;
&lt;br /&gt;
[[Image:JR-matlab-gui2.jpg | right | 800px]]&lt;br /&gt;
==SRAM Memory==&lt;br /&gt;
===SPI SRAM===&lt;br /&gt;
The project originally was going to use SPI SRAM from Microchip since you can find capacities around 256kbit with only 4 connections. Unfortunately I was unable to get this memory to work with the 5V PICS I was using. I tested the Microchip 23A256 and Winbound SPI SRAM chips. Neither of these chips run at 5V, the Microchip SRAM runs at 1.8V and the Winbound chip runs at 3.3V. I tried voltage dividers, diode drops and pull-ups with diodes and was unsuccessful at communicating with the SRAM chips.For communicating through SPI, there are several other pages on the wiki which discuss it more in detail.&lt;br /&gt;
===Parallel SRAM===&lt;br /&gt;
I instead used parallel memory in the final design, with the only downside that this memory requires 26 dedicated pins from the PIC (15 for address, 8 for data I/O and 3 for control). I wrote a small library for communicating with parallel memory located [here]. Notice that since so many pins are required, they will most likely always be different, so the pins are listed in order in arrays data_pins[] and address_pins[]. The parallel ram functions can be found here.  [[Media:Parallel_Mem.h | Parallel_Mem.h]]&lt;br /&gt;
==Code==&lt;br /&gt;
The code for the project can be found here.&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Master.c | Motor Control Master]]&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Slave.c | Motor Control Slave]]&lt;br /&gt;
&lt;br /&gt;
===Master PIC===&lt;br /&gt;
The Master PIC receives commands from MATLAB over RS232 and relays them to the slave over I2C. There are numerous articles in this wiki describing both RS232 between MATLAB and I2C communications.&lt;br /&gt;
&lt;br /&gt;
On the 18F4520 PIC, the hardware buffer for RS232 is only 3 characters long, and if that overflows, the RS232 communication shuts down. I found it necessary to implement an additional software buffer which pulled the characters from the RS232 interrupt and placed them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  #define rs_kbhit              (rs_nextIn != rs_nextOut)&lt;br /&gt;
&lt;br /&gt;
Which is analogous to the kbhit() function and returns true if there are new characters in the buffer.&lt;br /&gt;
&lt;br /&gt;
  #INT_RDA&lt;br /&gt;
  void rda_isr() {&lt;br /&gt;
     //fired when character is loaded into rs232 buffer (only 3 characters long)&lt;br /&gt;
     if(kbhit()) {&lt;br /&gt;
        //wait for buffer inputs&lt;br /&gt;
        //Load character into software rs232 buffer&lt;br /&gt;
        rsBuffer[rs_nextIn] = getc();&lt;br /&gt;
        rs_nextIn++;&lt;br /&gt;
        if(rs_nextIn&amp;gt;=RS232_BUFFER_SIZE) rs_nextIn = 0;&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The RS232 Interrupt pulls the characters from the hardware buffer and places them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  int8 rs_getc() {&lt;br /&gt;
     int8 c;&lt;br /&gt;
   &lt;br /&gt;
     while(!rs_kbhit);&lt;br /&gt;
     c = rsBuffer[rs_nextOut];&lt;br /&gt;
     rs_nextOut++;&lt;br /&gt;
     if(rs_nextOut &amp;gt; RS232_BUFFER_SIZE) rs_nextOut=0;&lt;br /&gt;
   &lt;br /&gt;
     return c;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
This function is to be used in the place of get_c().&lt;br /&gt;
&lt;br /&gt;
For the forwarding of MATLAB commands, the values sent through RS232 are put through a large switch to process them.&lt;br /&gt;
&lt;br /&gt;
===Slave PIC===&lt;br /&gt;
The Slave PIC used is an 18F4431 which has a quadrature encoder built in. Details on the 4431 can be found on the Robot Drummer project page. The commands sent from the Master PIC are processed in the SSP Interrupt so the PIC knows which values to get or set. The set commands are triggered through a dummy slave send command.&lt;br /&gt;
&lt;br /&gt;
  #INT_SSP high&lt;br /&gt;
  void ssp_isr() {&lt;br /&gt;
   disable_interrupts(GLOBAL);&lt;br /&gt;
   state = i2c_isr_state();&lt;br /&gt;
   if(state &amp;lt; 0x80)                 //master is sending data&lt;br /&gt;
   {&lt;br /&gt;
      if(state == 0)&lt;br /&gt;
      {&lt;br /&gt;
  &lt;br /&gt;
      }&lt;br /&gt;
      if(state == 1)                   //second received byte is command&lt;br /&gt;
      {&lt;br /&gt;
         command = i2c_read();&lt;br /&gt;
         bitCount=0;&lt;br /&gt;
      }&lt;br /&gt;
      if(state &amp;gt;= 2 &amp;amp;&amp;amp; state &amp;lt; 6)                   //other received bytes are data bytes&lt;br /&gt;
      {&lt;br /&gt;
         numBuf[state-2] = i2c_read();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   //have to do when state==0x80 since sending from slave gets buggy when more than one&lt;br /&gt;
   //state is used and cannot be state &amp;gt;= 0x80 since stop bit triggers a state increment&lt;br /&gt;
   if(state == 0x80)                //master is requesting data&lt;br /&gt;
   {&lt;br /&gt;
      switch(command) {&lt;br /&gt;
         case MC_GET_VELOCITY:&lt;br /&gt;
            i2c_write((int8)(vel_act&amp;gt;&amp;gt;(bitCount*8)));&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
      bitCount++;&lt;br /&gt;
    }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
The Slave PIC also implements a PD controller.&lt;br /&gt;
&lt;br /&gt;
  // Proportional Derivative Control&lt;br /&gt;
  void PID()                                           &lt;br /&gt;
  {&lt;br /&gt;
   updateStatus();&lt;br /&gt;
  &lt;br /&gt;
   velocity_count += vel_act;&lt;br /&gt;
   if(velocity_count &amp;lt; 0) {&lt;br /&gt;
      TargetPosition -= (velocity_count&amp;amp; 0x7FFFFFFF);      //negative velocity, need to convert to unsigned and subtract&lt;br /&gt;
      velocity_count = velocity_count &amp;amp; 0x800000FF;&lt;br /&gt;
   } else {&lt;br /&gt;
      TargetPosition += velocity_count;&lt;br /&gt;
      velocity_count = velocity_count &amp;amp; 0xFF;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   &lt;br /&gt;
   error = (signed int32) ((signed int32) TargetPosition - (signed int32) TotalCount);             // Compute proportional error&lt;br /&gt;
   derivative = error - last_error;                           // Compute Derivative Error&lt;br /&gt;
   last_error = error;&lt;br /&gt;
   &lt;br /&gt;
   duty = 1000;                                       // Set Duty to 50%&lt;br /&gt;
   duty += kp*error + kd*derivative;                  // Adjust Duty of motor (wrt to error)&lt;br /&gt;
   &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
   if (duty &amp;gt; 1990)                                   // Check for Saturation&lt;br /&gt;
   {&lt;br /&gt;
      duty = 1990;&lt;br /&gt;
   }&lt;br /&gt;
   else if (duty &amp;lt; 10)&lt;br /&gt;
   {&lt;br /&gt;
      duty = 10;&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   if(go == 1) {&lt;br /&gt;
     //record data&lt;br /&gt;
     if(dataCount &amp;lt; MEM_SIZE) {&lt;br /&gt;
        if((timeCount % timeInterval) == 0 ) {&lt;br /&gt;
           motorData[dataCount][0] = TargetPosition;&lt;br /&gt;
           motorData[dataCount][1] = TotalCount;&lt;br /&gt;
           dataCount++;&lt;br /&gt;
           output_d(dataCount);&lt;br /&gt;
        }&lt;br /&gt;
     } else {&lt;br /&gt;
        go = 0;&lt;br /&gt;
     }&lt;br /&gt;
   } else {&lt;br /&gt;
      duty = 1000;&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   disable_interrupts(GLOBAL);&lt;br /&gt;
   set_power_pwm0_duty((int16)duty);                  // Adjust PWM in response to PID control&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   &lt;br /&gt;
   timeCount++;&lt;br /&gt;
   &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The gains kp and kd are settable through MATLAB as you can tune your motor controller through the MATLAB interface. The variable &amp;#039;go&amp;#039; is used to tell the motor when to start motor operations, it also stops the motor when the correct amount of tracking data has been collected. The motor data is also stored in the PID() function. Since the PID fires every 400us, the variable timeInterval is used to break the collection into larger time chunks.&lt;br /&gt;
&lt;br /&gt;
==MATLAB GUI Programming==&lt;br /&gt;
The GUI for the controller is programmed through the GUIde feature of MATLAB. The code for the GUI is contained [here]. The difference between normal MATLAB programming and GUI programming is that there are no global variables for storing values that are easily creatable or accessible. If you want to access data from a GUI component, you have to through the &amp;#039;handles&amp;#039; structure, which is a structure containing all of the GUI components on your form. In order to access a string in a text-box, it has to be retrieved in the following manner:&lt;br /&gt;
  str = get(handles.textbox-1, &amp;#039;String&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
Also note that in GUI programming, every component has a Callback, which is called when an action is performed on a component (ie a button is pushed). Within the callback, three things are passed, the object itself called &amp;#039;hobject&amp;#039;, &amp;#039;eventData&amp;#039; which does nothing, and the &amp;#039;handles&amp;#039; structure. Utilizing callbacks are how you are able to perform actions based on interaction.&lt;br /&gt;
&lt;br /&gt;
If you want to store variables that you want to either access at a later time, or have variables that you can only create once (ie serial ports), then you have to store them in the application data structure. Application data can be placed and accessed in the following way:&lt;br /&gt;
  setappdata(hObject, &amp;#039;serialport&amp;#039;, sp)&lt;br /&gt;
  sp = getappdata(handles.pushbutton1, &amp;#039;serialport&amp;#039;)&lt;br /&gt;
where &amp;#039;serialport&amp;#039; is the name give in the structure, and sp is what you are storing, in this case an open serial port. Also note that since the application data was stored under pushbutton1, it has to always be accessed through that same component.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13620</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13620"/>
		<updated>2009-07-03T20:39:45Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MATLAB Motor Controller=&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. In this premise, the slave PIC controls the high speed motor with quadrature encoding. The slave PICs used are the 18f4431 since they have a built in quadrature encoder. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The slave PICs are controlled via I2C by the master PIC which is an 18f4520. The master PIC is controlled through MATLAB over RS-232. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;br /&gt;
&lt;br /&gt;
[[Image:JR-matlab-gui2.jpg | right | 800px]]&lt;br /&gt;
==SRAM Memory==&lt;br /&gt;
===SPI SRAM===&lt;br /&gt;
The project originally was going to use SPI SRAM from Microchip since you can find capacities around 256kbit with only 4 connections. Unfortunately I was unable to get this memory to work with the 5V PICS I was using. I tested the Microchip 23A256 and Winbound SPI SRAM chips. Neither of these chips run at 5V, the Microchip SRAM runs at 1.8V and the Winbound chip runs at 3.3V. I tried voltage dividers, diode drops and pull-ups with diodes and was unsuccessful at communicating with the SRAM chips.For communicating through SPI, there are several other pages on the wiki which discuss it more in detail.&lt;br /&gt;
===Parallel SRAM===&lt;br /&gt;
I instead used parallel memory in the final design, with the only downside that this memory requires 26 dedicated pins from the PIC (15 for address, 8 for data I/O and 3 for control). I wrote a small library for communicating with parallel memory located [here]. Notice that since so many pins are required, they will most likely always be different, so the pins are listed in order in arrays data_pins[] and address_pins[]. The parallel ram functions can be found here.  [[Media:Parallel_Mem.h | Parallel_Mem.h]]&lt;br /&gt;
==Code==&lt;br /&gt;
The code for the project can be found here.&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Master.c | Motor Control Master]]&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Slave.c | Motor Control Slave]]&lt;br /&gt;
&lt;br /&gt;
===Master PIC===&lt;br /&gt;
The Master PIC receives commands from MATLAB over RS232 and relays them to the slave over I2C. There are numerous articles in this wiki describing both RS232 between MATLAB and I2C communications.&lt;br /&gt;
&lt;br /&gt;
On the 18F4520 PIC, the hardware buffer for RS232 is only 3 characters long, and if that overflows, the RS232 communication shuts down. I found it necessary to implement an additional software buffer which pulled the characters from the RS232 interrupt and placed them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  #define rs_kbhit              (rs_nextIn != rs_nextOut)&lt;br /&gt;
&lt;br /&gt;
Which is analogous to the kbhit() function and returns true if there are new characters in the buffer.&lt;br /&gt;
&lt;br /&gt;
  #INT_RDA&lt;br /&gt;
  void rda_isr() {&lt;br /&gt;
     //fired when character is loaded into rs232 buffer (only 3 characters long)&lt;br /&gt;
     if(kbhit()) {&lt;br /&gt;
        //wait for buffer inputs&lt;br /&gt;
        //Load character into software rs232 buffer&lt;br /&gt;
        rsBuffer[rs_nextIn] = getc();&lt;br /&gt;
        rs_nextIn++;&lt;br /&gt;
        if(rs_nextIn&amp;gt;=RS232_BUFFER_SIZE) rs_nextIn = 0;&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The RS232 Interrupt pulls the characters from the hardware buffer and places them into the software buffer.&lt;br /&gt;
&lt;br /&gt;
  int8 rs_getc() {&lt;br /&gt;
     int8 c;&lt;br /&gt;
   &lt;br /&gt;
     while(!rs_kbhit);&lt;br /&gt;
     c = rsBuffer[rs_nextOut];&lt;br /&gt;
     rs_nextOut++;&lt;br /&gt;
     if(rs_nextOut &amp;gt; RS232_BUFFER_SIZE) rs_nextOut=0;&lt;br /&gt;
   &lt;br /&gt;
     return c;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
This function is to be used in the place of get_c().&lt;br /&gt;
&lt;br /&gt;
For the forwarding of MATLAB commands, the values sent through RS232 are put through a large switch to process them.&lt;br /&gt;
&lt;br /&gt;
==MATLAB GUI Programming==&lt;br /&gt;
The GUI for the controller is programmed through the GUIde feature of MATLAB. The code for the GUI is contained [here]. The difference between normal MATLAB programming and GUI programming is that there are no global variables for storing values that are easily creatable or accessible. If you want to access data from a GUI component, you have to through the &amp;#039;handles&amp;#039; structure, which is a structure containing all of the GUI components on your form. In order to access a string in a text-box, it has to be retrieved in the following manner:&lt;br /&gt;
  str = get(handles.textbox-1, &amp;#039;String&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
Also note that in GUI programming, every component has a Callback, which is called when an action is performed on a component (ie a button is pushed). Within the callback, three things are passed, the object itself called &amp;#039;hobject&amp;#039;, &amp;#039;eventData&amp;#039; which does nothing, and the &amp;#039;handles&amp;#039; structure. Utilizing callbacks are how you are able to perform actions based on interaction.&lt;br /&gt;
&lt;br /&gt;
If you want to store variables that you want to either access at a later time, or have variables that you can only create once (ie serial ports), then you have to store them in the application data structure. Application data can be placed and accessed in the following way:&lt;br /&gt;
  setappdata(hObject, &amp;#039;serialport&amp;#039;, sp)&lt;br /&gt;
  sp = getappdata(handles.pushbutton1, &amp;#039;serialport&amp;#039;)&lt;br /&gt;
where &amp;#039;serialport&amp;#039; is the name give in the structure, and sp is what you are storing, in this case an open serial port. Also note that since the application data was stored under pushbutton1, it has to always be accessed through that same component.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Motor_controller.m&amp;diff=13619</id>
		<title>File:Motor controller.m</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Motor_controller.m&amp;diff=13619"/>
		<updated>2009-07-03T20:01:24Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13618</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13618"/>
		<updated>2009-07-03T19:58:38Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MATLAB Motor Controller=&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. In this premise, the slave PIC controls the high speed motor with quadrature encoding. The slave PICs used are the 18f4431 since they have a built in quadrature encoder. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The slave PICs are controlled via I2C by the master PIC which is an 18f4520. The master PIC is controlled through MATLAB over RS-232. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;br /&gt;
&lt;br /&gt;
[[Image:JR-matlab-gui2.jpg | right | 800px]]&lt;br /&gt;
==SRAM Memory==&lt;br /&gt;
===SPI SRAM===&lt;br /&gt;
The project originally was going to use SPI SRAM from Microchip since you can find capacities around 256kbit with only 4 connections. Unfortunately I was unable to get this memory to work with the 5V PICS I was using. I tested the Microchip 23A256 and Winbound SPI SRAM chips. Neither of these chips run at 5V, the Microchip SRAM runs at 1.8V and the Winbound chip runs at 3.3V. I tried voltage dividers, diode drops and pull-ups with diodes and was unsuccessful at communicating with the SRAM chips.For communicating through SPI, there are several other pages on the wiki which discuss it more in detail.&lt;br /&gt;
===Parallel SRAM===&lt;br /&gt;
I instead used parallel memory in the final design, with the only downside that this memory requires 26 dedicated pins from the PIC (15 for address, 8 for data I/O and 3 for control). I wrote a small library for communicating with parallel memory located [here]. Notice that since so many pins are required, they will most likely always be different, so the pins are listed in order in arrays data_pins[] and address_pins[]. The parallel ram functions can be found here.  [[Media:Parallel_Mem.h | Parallel_Mem.h]]&lt;br /&gt;
==Code==&lt;br /&gt;
The code for the project can be found here.&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Master.c | Motor Control Master]]&lt;br /&gt;
&lt;br /&gt;
[[Media:Motor_Control_Slave.c | Motor Control Slave]]&lt;br /&gt;
&lt;br /&gt;
==MATLAB GUI Programming==&lt;br /&gt;
The GUI for the controller is programmed through the GUIde feature of MATLAB. The code for the GUI is contained [here]. The difference between normal MATLAB programming and GUI programming is that there are no global variables for storing values that are easily creatable or accessible. If you want to access data from a GUI component, you have to through the &amp;#039;handles&amp;#039; structure, which is a structure containing all of the GUI components on your form. In order to access a string in a text-box, it has to be retrieved in the following manner:&lt;br /&gt;
  str = get(handles.textbox-1, &amp;#039;String&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
Also note that in GUI programming, every component has a Callback, which is called when an action is performed on a component (ie a button is pushed). Within the callback, three things are passed, the object itself called &amp;#039;hobject&amp;#039;, &amp;#039;eventData&amp;#039; which does nothing, and the &amp;#039;handles&amp;#039; structure. Utilizing callbacks are how you are able to perform actions based on interaction.&lt;br /&gt;
&lt;br /&gt;
If you want to store variables that you want to either access at a later time, or have variables that you can only create once (ie serial ports), then you have to store them in the application data structure. Application data can be placed and accessed in the following way:&lt;br /&gt;
  setappdata(hObject, &amp;#039;serialport&amp;#039;, sp)&lt;br /&gt;
  sp = getappdata(handles.pushbutton1, &amp;#039;serialport&amp;#039;)&lt;br /&gt;
where &amp;#039;serialport&amp;#039; is the name give in the structure, and sp is what you are storing, in this case an open serial port. Also note that since the application data was stored under pushbutton1, it has to always be accessed through that same component.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Parallel_Mem.h&amp;diff=13617</id>
		<title>File:Parallel Mem.h</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Parallel_Mem.h&amp;diff=13617"/>
		<updated>2009-07-03T19:30:47Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Motor_Control_Slave.c&amp;diff=13616</id>
		<title>File:Motor Control Slave.c</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Motor_Control_Slave.c&amp;diff=13616"/>
		<updated>2009-07-03T19:29:59Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Motor_Control_Master.c&amp;diff=13615</id>
		<title>File:Motor Control Master.c</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Motor_Control_Master.c&amp;diff=13615"/>
		<updated>2009-07-03T19:29:34Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13614</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13614"/>
		<updated>2009-07-03T19:24:40Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MATLAB Motor Controller=&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. In this premise, the slave PIC controls the high speed motor with quadrature encoding. The slave PICs used are the 18f4431 since they have a built in quadrature encoder. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The slave PICs are controlled via I2C by the master PIC which is an 18f4520. The master PIC is controlled through MATLAB over RS-232. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;br /&gt;
&lt;br /&gt;
[[Image:JR-matlab-gui2.jpg | right | 800px]]&lt;br /&gt;
==SRAM Memory==&lt;br /&gt;
===SPI SRAM===&lt;br /&gt;
The project originally was going to use SPI SRAM from Microchip since you can find capacities around 256kbit with only 4 connections. Unfortunately I was unable to get this memory to work with the 5V PICS I was using. I tested the Microchip 23A256 and Winbound SPI SRAM chips. Neither of these chips run at 5V, the Microchip SRAM runs at 1.8V and the Winbound chip runs at 3.3V. I tried voltage dividers, diode drops and pull-ups with diodes and was unsuccessful at communicating with the SRAM chips.For communicating through SPI, there are several other pages on the wiki which discuss it more in detail.&lt;br /&gt;
===Parallel SRAM===&lt;br /&gt;
I instead used parallel memory in the final design, with the only downside that this memory requires 26 dedicated pins from the PIC (15 for address, 8 for data I/O and 3 for control). I wrote a small library for communicating with parallel memory located [here]. Notice that since so many pins are required, they will most likely always be different, so the pins are listed in order in arrays data_pins[] and address_pins[]. The parallel ram functions can be found here.  &lt;br /&gt;
==Code==&lt;br /&gt;
The code for the project can be found here.&lt;br /&gt;
==MATLAB GUI Programming==&lt;br /&gt;
The GUI for the controller is programmed through the GUIde feature of MATLAB. The code for the GUI is contained [here]. The difference between normal MATLAB programming and GUI programming is that there are no global variables for storing values that are easily creatable or accessible. If you want to access data from a GUI component, you have to through the &amp;#039;handles&amp;#039; structure, which is a structure containing all of the GUI components on your form. In order to access a string in a text-box, it has to be retrieved in the following manner:&lt;br /&gt;
  str = get(handles.textbox-1, &amp;#039;String&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
Also note that in GUI programming, every component has a Callback, which is called when an action is performed on a component (ie a button is pushed). Within the callback, three things are passed, the object itself called &amp;#039;hobject&amp;#039;, &amp;#039;eventData&amp;#039; which does nothing, and the &amp;#039;handles&amp;#039; structure. Utilizing callbacks are how you are able to perform actions based on interaction.&lt;br /&gt;
&lt;br /&gt;
If you want to store variables that you want to either access at a later time, or have variables that you can only create once (ie serial ports), then you have to store them in the application data structure. Application data can be placed and accessed in the following way:&lt;br /&gt;
  setappdata(hObject, &amp;#039;serialport&amp;#039;, sp)&lt;br /&gt;
  sp = getappdata(handles.pushbutton1, &amp;#039;serialport&amp;#039;)&lt;br /&gt;
where &amp;#039;serialport&amp;#039; is the name give in the structure, and sp is what you are storing, in this case an open serial port. Also note that since the application data was stored under pushbutton1, it has to always be accessed through that same component.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13613</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13613"/>
		<updated>2009-07-03T18:34:54Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MATLAB Motor Controller=&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. In this premise, the slave PIC controls the high speed motor with quadrature encoding. The slave PICs used are the 18f4431 since they have a built in quadrature encoder. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The slave PICs are controlled via I2C by the master PIC which is an 18f4520. The master PIC is controlled through MATLAB over RS-232. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;br /&gt;
[[Image:JR-matlab-gui2.jpg | right | 600px]]&lt;br /&gt;
==SRAM Memory==&lt;br /&gt;
===SPI SRAM===&lt;br /&gt;
The project originally was going to use SPI SRAM from Microchip since you can find capacities around 256kbit with only 4 connections. Unfortunately I was unable to get this memory to work with the 5V PICS I was using. For communicating through SPI, there are several other pages on the wiki such as [exp].&lt;br /&gt;
===Parallel SRAM===&lt;br /&gt;
I instead used parallel memory in the final design, with the only downside that this memory requires 26 dedicated pins from the PIC (15 for address, 8 for data I/O and 3 for control). I wrote a small library for communicating with parallel memory located [here]. Notice that since so many pins are required, they will most likely always be different, so the pins are listed in order in arrays data_pins[] and address_pins[].&lt;br /&gt;
==Code==&lt;br /&gt;
The code for the project can be found here.&lt;br /&gt;
==MATLAB GUI Programming==&lt;br /&gt;
The GUI for the controller is programmed through the GUIde feature of MATLAB. The code for the GUI is contained [here]. The difference between normal MATLAB programming and GUI programming is that there are no global variables for storing values that are easily creatable or accessible. If you want to access data from a GUI component, you have to through the &amp;#039;handles&amp;#039; structure, which is a structure containing all of the GUI components on your form. In order to access a string in a text-box, it has to be retrieved in the following manner:&lt;br /&gt;
  str = get(handles.textbox-1, &amp;#039;String&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
Also note that in GUI programming, every component has a Callback, which is called when an action is performed on a component (ie a button is pushed). Within the callback, three things are passed, the object itself called &amp;#039;hobject&amp;#039;, &amp;#039;eventData&amp;#039; which does nothing, and the &amp;#039;handles&amp;#039; structure. Utilizing callbacks are how you are able to perform actions based on interaction.&lt;br /&gt;
&lt;br /&gt;
If you want to store variables that you want to either access at a later time, or have variables that you can only create once (ie serial ports), then you have to store them in the application data structure. Application data can be placed and accessed in the following way:&lt;br /&gt;
  setappdata(hObject, &amp;#039;serialport&amp;#039;, sp)&lt;br /&gt;
  sp = getappdata(handles.pushbutton1, &amp;#039;serialport&amp;#039;)&lt;br /&gt;
where &amp;#039;serialport&amp;#039; is the name give in the structure, and sp is what you are storing, in this case an open serial port. Also note that since the application data was stored under pushbutton1, it has to always be accessed through that same component.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:JR-matlab-gui2.jpg&amp;diff=13612</id>
		<title>File:JR-matlab-gui2.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:JR-matlab-gui2.jpg&amp;diff=13612"/>
		<updated>2009-07-03T18:24:36Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13589</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13589"/>
		<updated>2009-06-15T14:28:46Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=MATLAB Motor Controller=&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. In this premise, the slave PIC controls the high speed motor with quadrature encoding. The slave PICs used are the 18f4431 since they have a built in quadrature encoder. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The slave PICs are controlled via I2C by the master PIC which is an 18f4520. The master PIC is controlled through MATLAB over RS-232. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;br /&gt;
[[Image:JR-matlab-gui.jpg | right | 600px]]&lt;br /&gt;
==SRAM Memory==&lt;br /&gt;
===SPI SRAM===&lt;br /&gt;
The project originally was going to use SPI SRAM from Microchip since you can find capacities around 256kbit with only 4 connections. Unfortunately I was unable to get this memory to work with the 5V PICS I was using. For communicating through SPI, there are several other pages on the wiki such as [exp].&lt;br /&gt;
===Parallel SRAM===&lt;br /&gt;
I instead used parallel memory in the final design, with the only downside that this memory requires 26 dedicated pins from the PIC (15 for address, 8 for data I/O and 3 for control). I wrote a small library for communicating with parallel memory located [here]. Notice that since so many pins are required, they will most likely always be different, so the pins are listed in order in arrays data_pins[] and address_pins[].&lt;br /&gt;
==Code==&lt;br /&gt;
The code for the project can be found here.&lt;br /&gt;
==MATLAB GUI Programming==&lt;br /&gt;
The GUI for the controller is programmed through the GUIde feature of MATLAB. The code for the GUI is contained [here]. The difference between normal MATLAB programming and GUI programming is that there are no global variables for storing values that are easily creatable or accessible. If you want to access data from a GUI component, you have to through the &amp;#039;handles&amp;#039; structure, which is a structure containing all of the GUI components on your form. In order to access a string in a text-box, it has to be retrieved in the following manner:&lt;br /&gt;
  str = get(handles.textbox-1, &amp;#039;String&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
Also note that in GUI programming, every component has a Callback, which is called when an action is performed on a component (ie a button is pushed). Within the callback, three things are passed, the object itself called &amp;#039;hobject&amp;#039;, &amp;#039;eventData&amp;#039; which does nothing, and the &amp;#039;handles&amp;#039; structure. Utilizing callbacks are how you are able to perform actions based on interaction.&lt;br /&gt;
&lt;br /&gt;
If you want to store variables that you want to either access at a later time, or have variables that you can only create once (ie serial ports), then you have to store them in the application data structure. Application data can be placed and accessed in the following way:&lt;br /&gt;
  setappdata(hObject, &amp;#039;serialport&amp;#039;, sp)&lt;br /&gt;
  sp = getappdata(handles.pushbutton1, &amp;#039;serialport&amp;#039;)&lt;br /&gt;
where &amp;#039;serialport&amp;#039; is the name give in the structure, and sp is what you are storing, in this case an open serial port. Also note that since the application data was stored under pushbutton1, it has to always be accessed through that same component.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:JR-matlab-gui.jpg&amp;diff=13588</id>
		<title>File:JR-matlab-gui.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:JR-matlab-gui.jpg&amp;diff=13588"/>
		<updated>2009-06-15T13:59:35Z</updated>

		<summary type="html">&lt;p&gt;John Rula: Controller GUI for MATLAB&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Controller GUI for MATLAB&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13587</id>
		<title>MATLAB Motor Controller</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=MATLAB_Motor_Controller&amp;diff=13587"/>
		<updated>2009-06-15T13:59:07Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MATLAB Motor Controller&lt;br /&gt;
This project expands on the work done by Matt Turpin and his I2C Motor Controller. The slave PICs implement volatile SRAM to track motor positions to aid in control tuning. The motors can be monitored, controlled and tracked through a MATLAB GUI (shown below).&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Projects_and_miscellaneous&amp;diff=13586</id>
		<title>Projects and miscellaneous</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Projects_and_miscellaneous&amp;diff=13586"/>
		<updated>2009-06-15T13:54:36Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[ME 333 final projects]]&lt;br /&gt;
*[[PIC Motor Control with EEPROM and Interactive Menu Example]]&lt;br /&gt;
*[[Machine Vision Localization System]]&lt;br /&gt;
*[[Swarm Robot Project]]&lt;br /&gt;
*[[Swarm Project E-puck Code]]&lt;br /&gt;
*[[Swarm Robot Project Documentation]]&lt;br /&gt;
*[[Machine Vision Localization System]]&lt;br /&gt;
*[[Indoor Localization System | Indoor Localization System (Obsolete)]]&lt;br /&gt;
*[[Robot Helicopter Project]]&lt;br /&gt;
*[[E-Puck Color Sensing Project]]&lt;br /&gt;
*[[Guitar Tuning Project]]&lt;br /&gt;
*[[Mohr&amp;#039;s Circle]]&lt;br /&gt;
*[[E-puck Mobile Robot]]&lt;br /&gt;
*[[Bearings]]&lt;br /&gt;
*[[Indoor Localization System]]&lt;br /&gt;
*[[Using the Basic Stamp Microcontroller]]&lt;br /&gt;
*[[Basic Stamp]]&lt;br /&gt;
*[[Solderboard]]&lt;br /&gt;
*[[Battery disaster]]&lt;br /&gt;
*[[LIMS Air Hockey Table]]&lt;br /&gt;
*[[Rotational Stiffness]]&lt;br /&gt;
*[[Swarm E-puck Quickstart Guide]]&lt;br /&gt;
*[[High Speed Vision System and Object Tracking]]&lt;br /&gt;
*[[PIC USB]]&lt;br /&gt;
*[[MATLAB Motor Controller]]&lt;br /&gt;
*[[Flexure Characterization and Design]]&lt;br /&gt;
*[[Bouncing Polygon Simulator]]&lt;br /&gt;
*[[MonkeyBot Simulation Project]]&lt;br /&gt;
*[[PPOD-mini Project]]&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=12945</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=12945"/>
		<updated>2009-03-20T08:56:12Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Basketball */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See the &amp;#039;&amp;#039;&amp;#039;[[ME 333 end of course schedule]]&amp;#039;&amp;#039;&amp;#039;.  &lt;br /&gt;
&lt;br /&gt;
Final projects for ME 333 in years 2000-2007 can be found&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;[http://lims.mech.northwestern.edu/~design/mechatronics/ here]&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2009 ==&lt;br /&gt;
&lt;br /&gt;
=== [[Mozart&amp;#039;s Right Hand]] ===&lt;br /&gt;
[[Image:mrh_box.JPG|thumb|150px|Mozart&amp;#039;s Right Hand|right]]&lt;br /&gt;
Mozart&amp;#039;s Right Hand is a musical instrument capable of playing two full octaves of the [http://en.wikipedia.org/wiki/Diatonic_scale Diatonic Scale.]  The user wears a glove on his right hand and uses motions of the hand and fingers to create different notes that are played with a speaker.  The pitch of the note is controlled by the orientation of the user&amp;#039;s hand as he rotates it ether from the wrist, the elbow, or the shoulder.  The LCD on the front of the box tells the user the pitch that corresponds to his or her current hand orientation.  When the user touches together his thumb and index finger, the speaker plays the tone.  A [http://www.youtube.com/watch?v=vec-W4QeHQU video] of Mozart&amp;#039;s Right Hand in action is available on YouTube.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Persistence-of-Vision Display]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Rock Paper Scissors Machine]] ===&lt;br /&gt;
[[Image:rps whole thing.JPG|thumb|150px|Rock Paper Scissors Machine|right]]&lt;br /&gt;
A machine that will play a fully functioning, intuitive game of [http://en.wikipedia.org/wiki/Rock-paper-scissors Rock/Paper/Scissors] (abbreviated as RPS) with a user. The machine is represented by a human-like hand, capable of seperate and independant wrist, arm, finger and thumb motion. The players&amp;#039; hand goes into a glove equipped with flex sensors, which wirelessly transmits data to the machine based on what the player chose. The machine then reads this data, randomly chooses a throw of its own, and displays what the machine threw, what the human threw, total win/loss/tie info, and winner/loser both on an [http://en.wikipedia.org/wiki/Lcd LCD] screen and in the form of a thumbs up/down/side motion. Video of the machine in action can be found [http://www.youtube.com/watch?v=xbLNBSTTrcE here.]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Three-speaker Chladni Patterns]] ===&lt;br /&gt;
[[Image:chladni_660hz|right|thumb|150px]]&lt;br /&gt;
This project uses three speakers to generate shapes on a circular aluminum plate depending on which frequency the speakers are playing at. Once the speakers hit a resonant frequency of the plate, salt migrates to the nodes (zero amplitude) regions of the plate to form distinct patterns.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Basketball]] ===&lt;br /&gt;
[[Image:Mechatronics2009Bball|right|thumb|150px]]&lt;br /&gt;
This project consists of a throwing arm propelled by a Pittman motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot; A video can be found [http://www.youtube.com/watch?v=Y466dzP-qiY here].&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Drummer]] ===&lt;br /&gt;
[[Image:Robot_Drummer.jpg|thumb|400pix|right|Robot Drummer]]&lt;br /&gt;
The Robot Drummer is a device that demonstrates high-speed motor control by being able to drum when given commands.  Through an RS232 cable, Matlab sends commands to a &amp;quot;master&amp;quot; PIC.  The master then sends the commands to two &amp;quot;slave&amp;quot; PICs through I2C communication.  The slaves take the commands and implement PID control of the motors.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Fish Refuge]] ===&lt;br /&gt;
[[Image:Entire Fish Refuge|right|thumb|200px]]&lt;br /&gt;
The automated fish refuge allows for the controlled movement of a fish refuge with the goal of recording specific behavior.  The mechanical design is completely adjustable and allows adjustable degrees of oscillating movement and orientation of the refuge.  The program is primarily in MATLAB for ease of use and the velocity profile can be a sine, square, triangle, or any function that the user inputs. [http://www.youtube.com/watch?v=wGOKujMhN88 Check out the video!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Marionette]] ===&lt;br /&gt;
[[Image: MarionettePicForIntro.JPG|right|thumb]] The Marionette Project focused on using RC Servos to make a puppet that would do a dance with the press of a button.  There were 5 different dances programmed for the marionette, showcasing different styles of movement.  The movement had 2 degrees of freedom thanks to using 5 bar linkages and 2 RC servos for each arm.  Two more RC Servos were used on the back of the marionette to create the appearance of leg movement.  The movements included a Hula dance, Jumping Jacks, and even some moves right out of Saturday Night Fever.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Monkeybot]] ===&lt;br /&gt;
[[Image:monkeybot_pic|thumb|right|200px|Moneybot]]&lt;br /&gt;
The monkeybot, is a swinging robot capable of moving side to side and climbing.  It consists of a two link, double pendulum system with an electro-magnet on each end.  At the pivot is a DC motor, which provides an input torque and allows the swinging system to gain energy and climb.  Check out the video of the monkeybot climbing [http://www.youtube.com/watch?v=TA2VcH_GDJ0 here].   &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[PPOD-mini:  6-DOF Shaker]] ===&lt;br /&gt;
[[Image:PPOD_mini.JPG|thumb|200x200 px|right|PPOD-mini 6-DOF Shaker]]&lt;br /&gt;
The PPOD-mini is a miniaturized version of the Programmable Part-feeding Oscillatory Device ([http://lims.mech.northwestern.edu/projects/frictioninducedforcefields/index.htm PPOD]) found in the Laboratory for Intelligent Mechanical Systems (LIMS) at Northwestern. The PPOD-mini utilizes six speakers that act like actuators. The speakers are connected to a acrylic plate via flexures of tygon and iron. In its current implementation, the phase of the speakers can be controlled independently, giving the device six degrees of freedom. The movement of objects placed on the acrylic plate can be controlled by changing the phases of the speakers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Xylophone]] ===&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|200x200 px|right|Automated Xylophone]]&lt;br /&gt;
The Automated Xylophone controls several solenoids which hit various pitches on an actual xylophone based on the note selected.  The device has two main modes: using the keypad, a user can choose to either play notes in real time or store songs to be played back later.  A video of the Automated Xylophone playing in real time mode can be found [http://www.youtube.com/watch?v=_ubpAEyq9kg here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vision-based Cannon]] ===&lt;br /&gt;
[[Image:SM_Gun_Camera_PIC_Setup.JPG|thumb|200x200 px|right|Vision-based Cannon]]&lt;br /&gt;
This project uses a webcam and Matlab to analyze an image and direct a modified USB Missile Launcher to fire at targets found in the image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axes, and then tracks the emitter with a laser. [[Media:MT_MS_AZ_TrackerVideo.mp4|See Spot Run.]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This remote control robotic snake uses servo motors with a traveling sine wave motion profile to mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
[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_system.JPG|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This prototype is a proof of concept model of a variable ratio transmission to be implemented in the 2008-2009 Formula SAE competition vehicle.  The gear ratio is determined by the distances between the pulley halves which are controllable electronically.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
[[Image:Team-21-main-picture.JPG|right|thumb|200px]]&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=KhgTNCfdwZw Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|Sweet Baseball Game|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Ballbalancechallenge.JPG|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive game involving ball balancing on a touchscreen with touchscreen feedback and joystick action. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12943</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12943"/>
		<updated>2009-03-20T08:51:56Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two PICs communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
We used two PICs for this project. One ran the motor control since we wanted the smallest interrupt possible for the most accurate speed control. The other PIC ran the servo attached to the turntable as well as the infrared and ultrasonic sensors.&lt;br /&gt;
 &lt;br /&gt;
The motor was controlled using a PD controller which controlled both speed and position. Theory behind the controller was that if accurate speed control could be achieved along with the ability to control the release point by stopping the motor, we could control the distance the ball traveled to a high degree of accuracy having it follow simple kinematic equations. The launch was triggered when the ultrasonic sensor distance was sent to it. We opted against I2C and instead went with RS-232 for simplicity since we were only sending two bytes of data.&lt;br /&gt;
 &lt;br /&gt;
The turntable PIC controlled the RC servo, infrared emitter, infrared phototransistor, and PING ultrasonic ranger. The servo cycled through its full range while recording the maximum value from the phototransistor and its position in the servo cycle, returning to the position of maximum infrared light. The [[Ultrasonic_ranging|PING]] ultrasonic ranger was then used to determine the distance, which was then sent over RS-232 to the motor controlling PIC.&lt;br /&gt;
&lt;br /&gt;
Full source code of the motor controller can be found [[Media:Motor-Control.c|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
Full source code of the turntable controller can be found [[Media:Turntable-Control.c|here]]&lt;br /&gt;
&lt;br /&gt;
== Turntable Control ==&lt;br /&gt;
 for (maxvalue=0; RCservo0&amp;gt;(1500+4000)/8; RCservo0-=1){&lt;br /&gt;
     delay_us(500);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 for (RCservo0=(1500+4000)/8;  RCservo0&amp;lt;(12500-1000)/8; RCservo0+=1  ) {&lt;br /&gt;
    value = read_adc();&lt;br /&gt;
    output_d(value&amp;gt;&amp;gt;2);     // on port D show only the most significant 8 of the 10 bits; tricky &amp;gt;&amp;gt; means shift right 2 bits&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    if (value&amp;gt;maxvalue) {&lt;br /&gt;
       hoopposition=RCservo0;              //record position where max ir reflection was detected (the position of the hoop)&lt;br /&gt;
       maxvalue=value;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
     &lt;br /&gt;
  for (RCservo0=(12500-1000)/8; RCservo0&amp;gt;hoopposition+15; RCservo0-=1 ) {&lt;br /&gt;
    delay_us(500);&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  RCservo0=hoopposition+15;                         //move servo to hoop position&lt;br /&gt;
  delay_ms(2000);&lt;br /&gt;
  avgdistance=0;&lt;br /&gt;
 &lt;br /&gt;
  for (counter=0; counter&amp;lt;11; counter+=1) {            //distance sensing loop&lt;br /&gt;
    output_high(PIN_C5);&lt;br /&gt;
    delay_us(5);       &lt;br /&gt;
    output_low(PIN_C5);&lt;br /&gt;
    input(PIN_C5);&lt;br /&gt;
    delay_ms(20); //changed from 20&lt;br /&gt;
    avgdistance = avgdistance+distance;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== PD Controller ==&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; &lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount;&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
We used hardware encoders due to the speed of rotation of the shaft.&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
Theta was used for position control. Due to the way we implemented it, the motor was only was only allowed 359.9 degrees of rotation which was suitable for our launching arm.&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
A positive thetaError indicated that the motor needed to move CCW to reach its destination A negative thetaError indicated that the motor needed to move CW to reach its destination.&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
 &lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
The encoderTargetTheta was used to handle the case of overshoots and was the theta value of the encoderTarget after the speed was added. If that theta value was above/below (depending on direction) the target theta value, it represented that the input had reached its destination, so the speed drops to zero, and the encoderTarget is set to the correct target value.&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
In tuning the PD controller, it was found that different speeds needed different tunings in order to receive a smooth and accurate response. These values represent the best values we were able to obtain in tuning.&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
Set PWM values to make motor go forward or reverse. Also, the case where &amp;#039;launching==1&amp;#039; is to return the arm to a loading position after the arm has shot a ball.&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Set the motor&amp;#039;s PWM and check for maximum and minimum values. 624 was used instead of 78 for PWM values based on how we set up our timer2.&lt;br /&gt;
&lt;br /&gt;
== PIC to PIC communication with RS-232 ==&lt;br /&gt;
We choose to use RS-232 to communicate between PICs because of the small amount of data we were sending (a single int16) and to avoid the overhead required by I2C. We accomplished this by breaking our values into 8-bit chunks cast as chars and sending them one at a time.&lt;br /&gt;
&lt;br /&gt;
 sendDistance = avgdistance*100; //distance in cm\&lt;br /&gt;
 &lt;br /&gt;
 //Break distance into two 8-bit ints and cast as chars to send over RS-232&lt;br /&gt;
 //Will be reassembled on other pic&lt;br /&gt;
 putc((char)(sendDistance&amp;gt;&amp;gt;8));&lt;br /&gt;
 putc((char)(sendDistance &amp;amp; 255));&lt;br /&gt;
Code to send value.&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
This interrupt is called when the hardware RS-232 receives a byte of data. Once two bytes of data are received (int16), the interrupt reassembles them into a single int16 and calls CalculateAndLaunch().&lt;br /&gt;
&lt;br /&gt;
== Distance Calculation ==&lt;br /&gt;
Shot distance was based on a second order polynomial fit we obtained experimentally. The data we collected is shown in the image on the right. [[Image:Distance-Calibration-basketball.png|Calibration data and Trendline|thumb|250px|right]]&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Y466dzP-qiY Link To Video]&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12940</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12940"/>
		<updated>2009-03-20T08:48:52Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two PICs communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
We used two PICs for this project. One ran the motor control since we wanted the smallest interrupt possible for the most accurate speed control. The other PIC ran the servo attached to the turntable as well as the infrared and ultrasonic sensors.&lt;br /&gt;
 &lt;br /&gt;
The motor was controlled using a PD controller which controlled both speed and position. Theory behind the controller was that if accurate speed control could be achieved along with the ability to control the release point by stopping the motor, we could control the distance the ball traveled to a high degree of accuracy having it follow simple kinematic equations. The launch was triggered when the ultrasonic sensor distance was sent to it. We opted against I2C and instead went with RS-232 for simplicity since we were only sending two bytes of data.&lt;br /&gt;
 &lt;br /&gt;
The turntable PIC controlled the RC servo, infrared emitter, infrared phototransistor, and PING ultrasonic ranger. The servo cycled through its full range while recording the maximum value from the phototransistor and its position in the servo cycle, returning to the position of maximum infrared light. The [[Ultrasonic_ranging|PING]] ultrasonic ranger was then used to determine the distance, which was then sent over RS-232 to the motor controlling PIC.&lt;br /&gt;
&lt;br /&gt;
Full source code of the motor controller can be found [[Media:Motor-Control.c|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
Full source code of the turntable controller can be found [[Media:Turntable-Control.c|here]]&lt;br /&gt;
&lt;br /&gt;
== PD Controller ==&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; &lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount;&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
We used hardware encoders due to the speed of rotation of the shaft.&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
Theta was used for position control. Due to the way we implemented it, the motor was only was only allowed 359.9 degrees of rotation which was suitable for our launching arm.&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
A positive thetaError indicated that the motor needed to move CCW to reach its destination A negative thetaError indicated that the motor needed to move CW to reach its destination.&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
 &lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
The encoderTargetTheta was used to handle the case of overshoots and was the theta value of the encoderTarget after the speed was added. If that theta value was above/below (depending on direction) the target theta value, it represented that the input had reached its destination, so the speed drops to zero, and the encoderTarget is set to the correct target value.&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
In tuning the PD controller, it was found that different speeds needed different tunings in order to receive a smooth and accurate response. These values represent the best values we were able to obtain in tuning.&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
Set PWM values to make motor go forward or reverse. Also, the case where &amp;#039;launching==1&amp;#039; is to return the arm to a loading position after the arm has shot a ball.&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Set the motor&amp;#039;s PWM and check for maximum and minimum values. 624 was used instead of 78 for PWM values based on how we set up our timer2.&lt;br /&gt;
&lt;br /&gt;
== PIC to PIC communication with RS-232 ==&lt;br /&gt;
We choose to use RS-232 to communicate between PICs because of the small amount of data we were sending (a single int16) and to avoid the overhead required by I2C. We accomplished this by breaking our values into 8-bit chunks cast as chars and sending them one at a time.&lt;br /&gt;
&lt;br /&gt;
 sendDistance = avgdistance*100; //distance in cm\&lt;br /&gt;
 &lt;br /&gt;
 //Break distance into two 8-bit ints and cast as chars to send over RS-232&lt;br /&gt;
 //Will be reassembled on other pic&lt;br /&gt;
 putc((char)(sendDistance&amp;gt;&amp;gt;8));&lt;br /&gt;
 putc((char)(sendDistance &amp;amp; 255));&lt;br /&gt;
Code to send value.&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
This interrupt is called when the hardware RS-232 receives a byte of data. Once two bytes of data are received (int16), the interrupt reassembles them into a single int16 and calls CalculateAndLaunch().&lt;br /&gt;
&lt;br /&gt;
== Distance Calculation ==&lt;br /&gt;
Shot distance was based on a second order polynomial fit we obtained experimentally. The data we collected is shown in the image on the right. [[Image:Distance-Calibration-basketball.png|Calibration data and Trendline|thumb|250px|right]]&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Y466dzP-qiY Link To Video]&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12926</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12926"/>
		<updated>2009-03-20T08:30:41Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* PIC to PIC communication with RS-232 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two PICs communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
We used two PICs for this project. One ran the motor control since we wanted the smallest interrupt possible for the most accurate speed control. The other PIC ran the servo attached to the turntable as well as the infrared and ultrasonic sensors.&lt;br /&gt;
 &lt;br /&gt;
The motor was controlled using a PD controller which controlled both speed and position. Theory behind the controller was that if accurate speed control could be achieved along with the ability to control the release point by stopping the motor, we could control the distance the ball traveled to a high degree of accuracy having it follow simple kinematic equations. The launch was triggered when the ultrasonic sensor distance was sent to it. We opted against I2C and instead went with RS-232 for simplicity since we were only sending two bytes of data.&lt;br /&gt;
&lt;br /&gt;
Full source code of the motor controller can be found [[Media:Motor-Control.c|here]].&lt;br /&gt;
&lt;br /&gt;
== PD Controller ==&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; &lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount;&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
We used hardware encoders due to the speed of rotation of the shaft.&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
Theta was used for position control. Due to the way we implemented it, the motor was only was only allowed 359.9 degrees of rotation which was suitable for our launching arm.&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
A positive thetaError indicated that the motor needed to move CCW to reach its destination A negative thetaError indicated that the motor needed to move CW to reach its destination.&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
 &lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
The encoderTargetTheta was used to handle the case of overshoots and was the theta value of the encoderTarget after the speed was added. If that theta value was above/below (depending on direction) the target theta value, it represented that the input had reached its destination, so the speed drops to zero, and the encoderTarget is set to the correct target value.&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
In tuning the PD controller, it was found that different speeds needed different tunings in order to receive a smooth and accurate response. These values represent the best values we were able to obtain in tuning.&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
Set PWM values to make motor go forward or reverse. Also, the case where &amp;#039;launching==1&amp;#039; is to return the arm to a loading position after the arm has shot a ball.&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Set the motor&amp;#039;s PWM and check for maximum and minimum values. 624 was used instead of 78 for PWM values based on how we set up our timer2.&lt;br /&gt;
&lt;br /&gt;
== PIC to PIC communication with RS-232 ==&lt;br /&gt;
We choose to use RS-232 to communicate between PICs because of the small amount of data we were sending (a single int16) and to avoid the overhead required by I2C. We accomplished this by breaking our values into 8-bit chunks cast as chars and sending them one at a time.&lt;br /&gt;
&lt;br /&gt;
 sendDistance = avgdistance*100; //distance in cm\&lt;br /&gt;
 &lt;br /&gt;
 //Break distance into two 8-bit ints and cast as chars to send over RS-232&lt;br /&gt;
 //Will be reassembled on other pic&lt;br /&gt;
 putc((char)(sendDistance&amp;gt;&amp;gt;8));&lt;br /&gt;
 putc((char)(sendDistance &amp;amp; 255));&lt;br /&gt;
Code to send value.&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
This interrupt is called when the hardware RS-232 receives a byte of data. Once two bytes of data are received (int16), the interrupt reassembles them into a single int16 and calls CalculateAndLaunch().&lt;br /&gt;
&lt;br /&gt;
== Distance Calculation ==&lt;br /&gt;
Shot distance was based on a second order polynomial fit we obtained experimentally. The data we collected is shown in the image on the right. [[Image:Distance-Calibration-basketball.png|Calibration data and Trendline|thumb|250px|right]]&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Y466dzP-qiY Link To Video]&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12924</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12924"/>
		<updated>2009-03-20T08:30:06Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Distance Calculation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two PICs communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
We used two PICs for this project. One ran the motor control since we wanted the smallest interrupt possible for the most accurate speed control. The other PIC ran the servo attached to the turntable as well as the infrared and ultrasonic sensors.&lt;br /&gt;
 &lt;br /&gt;
The motor was controlled using a PD controller which controlled both speed and position. Theory behind the controller was that if accurate speed control could be achieved along with the ability to control the release point by stopping the motor, we could control the distance the ball traveled to a high degree of accuracy having it follow simple kinematic equations. The launch was triggered when the ultrasonic sensor distance was sent to it. We opted against I2C and instead went with RS-232 for simplicity since we were only sending two bytes of data.&lt;br /&gt;
&lt;br /&gt;
Full source code of the motor controller can be found [[Media:Motor-Control.c|here]].&lt;br /&gt;
&lt;br /&gt;
== PD Controller ==&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; &lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount;&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
We used hardware encoders due to the speed of rotation of the shaft.&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
Theta was used for position control. Due to the way we implemented it, the motor was only was only allowed 359.9 degrees of rotation which was suitable for our launching arm.&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
A positive thetaError indicated that the motor needed to move CCW to reach its destination A negative thetaError indicated that the motor needed to move CW to reach its destination.&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
 &lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
The encoderTargetTheta was used to handle the case of overshoots and was the theta value of the encoderTarget after the speed was added. If that theta value was above/below (depending on direction) the target theta value, it represented that the input had reached its destination, so the speed drops to zero, and the encoderTarget is set to the correct target value.&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
In tuning the PD controller, it was found that different speeds needed different tunings in order to receive a smooth and accurate response. These values represent the best values we were able to obtain in tuning.&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
Set PWM values to make motor go forward or reverse. Also, the case where &amp;#039;launching==1&amp;#039; is to return the arm to a loading position after the arm has shot a ball.&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Set the motor&amp;#039;s PWM and check for maximum and minimum values. 624 was used instead of 78 for PWM values based on how we set up our timer2.&lt;br /&gt;
&lt;br /&gt;
== PIC to PIC communication with RS-232 ==&lt;br /&gt;
We choose to use RS-232 to communicate between PICs because of the small amount of data we were sending (a single int16) and to avoid the overhead required by I2C. We accomplished this by breaking our values into 8-bit chunks cast as chars and sending them one at a time.&lt;br /&gt;
&lt;br /&gt;
 sendDistance = avgdistance*100; //distance in cm\&lt;br /&gt;
 &lt;br /&gt;
 //Break distance into two 8-bit ints and cast as chars to send over RS-232&lt;br /&gt;
 //Will be reassembled on other pic&lt;br /&gt;
 putc((char)(sendDistance&amp;gt;&amp;gt;8));&lt;br /&gt;
 putc((char)(sendDistance &amp;amp; 255));&lt;br /&gt;
Code to send value.&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
This interrupt is called when the hardware RS-232 receives a byte of data. Once two bytes of data are received (int16), the interrupt reassembles them into a single int16 and calls CalculateAndLaunch().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 78, 16);&lt;br /&gt;
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);     //Counter used for Encoder A -- Up Count&lt;br /&gt;
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);     //Counter used for Encoder B -- Down Count&lt;br /&gt;
&lt;br /&gt;
   //setup offsets and intialize encoders&lt;br /&gt;
   upCount = get_timer0();&lt;br /&gt;
   downCount = get_timer1();&lt;br /&gt;
   lastUpCount = upCount;&lt;br /&gt;
   lastDownCount = downCount;&lt;br /&gt;
  &lt;br /&gt;
   encoderActual += (upCount - downCount);&lt;br /&gt;
 &lt;br /&gt;
   initialCount = encoderActual;&lt;br /&gt;
 &lt;br /&gt;
   offset = encoderActual%EncCount;&lt;br /&gt;
   if(encoderActual &amp;lt; 0) offset = -offset;&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   ext_int_edge(0, H_TO_L);      // interrupt on INT0/RB0 pin, low to high transition&lt;br /&gt;
   setup_ccp1(CCP_PWM);&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(0);&lt;br /&gt;
   output_low(PIN_C4);&lt;br /&gt;
   delay_us(10);&lt;br /&gt;
 &lt;br /&gt;
   while(TRUE) {&lt;br /&gt;
      delay_ms(5000);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
== Distance Calculation ==&lt;br /&gt;
Shot distance was based on a second order polynomial fit we obtained experimentally. The data we collected is shown in the image on the right. [[Image:Distance-Calibration-basketball.png|Calibration data and Trendline|thumb|250px|right]]&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Y466dzP-qiY Link To Video]&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Distance-Calibration-basketball.png&amp;diff=12916</id>
		<title>File:Distance-Calibration-basketball.png</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Distance-Calibration-basketball.png&amp;diff=12916"/>
		<updated>2009-03-20T08:16:08Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12915</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12915"/>
		<updated>2009-03-20T08:15:42Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Distance Calculation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two PICs communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
We used two PICs for this project. One ran the motor control since we wanted the smallest interrupt possible for the most accurate speed control. The other PIC ran the servo attached to the turntable as well as the infrared and ultrasonic sensors.&lt;br /&gt;
 &lt;br /&gt;
The motor was controlled using a PD controller which controlled both speed and position. Theory behind the controller was that if accurate speed control could be achieved along with the ability to control the release point by stopping the motor, we could control the distance the ball traveled to a high degree of accuracy having it follow simple kinematic equations. The launch was triggered when the ultrasonic sensor distance was sent to it. We opted against I2C and instead went with RS-232 for simplicity since we were only sending two bytes of data.&lt;br /&gt;
&lt;br /&gt;
Full source code of the motor controller can be found [[Media:Motor-Control.c|here]].&lt;br /&gt;
&lt;br /&gt;
== PD Controller ==&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; &lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount;&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
We used hardware encoders due to the speed of rotation of the shaft.&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
Theta was used for position control. Due to the way we implemented it, the motor was only was only allowed 359.9 degrees of rotation which was suitable for our launching arm.&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
A positive thetaError indicated that the motor needed to move CCW to reach its destination A negative thetaError indicated that the motor needed to move CW to reach its destination.&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
 &lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
The encoderTargetTheta was used to handle the case of overshoots and was the theta value of the encoderTarget after the speed was added. If that theta value was above/below (depending on direction) the target theta value, it represented that the input had reached its destination, so the speed drops to zero, and the encoderTarget is set to the correct target value.&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
In tuning the PD controller, it was found that different speeds needed different tunings in order to receive a smooth and accurate response. These values represent the best values we were able to obtain in tuning.&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
Set PWM values to make motor go forward or reverse. Also, the case where &amp;#039;launching==1&amp;#039; is to return the arm to a loading position after the arm has shot a ball.&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Set the motor&amp;#039;s PWM and check for maximum and minimum values. 624 was used instead of 78 for PWM values based on how we set up our timer2.&lt;br /&gt;
&lt;br /&gt;
== PIC to PIC communication with RS-232 ==&lt;br /&gt;
We choose to use RS-232 to communicate between PICs because of the small amount of data we were sending (a single int16) and to avoid the overhead required by I2C. We accomplished this by breaking our values into 8-bit chunks cast as chars and sending them one at a time.&lt;br /&gt;
&lt;br /&gt;
 sendDistance = avgdistance*100; //distance in cm\&lt;br /&gt;
 &lt;br /&gt;
 //Break distance into two 8-bit ints and cast as chars to send over RS-232&lt;br /&gt;
 //Will be reassembled on other pic&lt;br /&gt;
 putc((char)(sendDistance&amp;gt;&amp;gt;8));&lt;br /&gt;
 putc((char)(sendDistance &amp;amp; 255));&lt;br /&gt;
Code to send value.&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
This interrupt is called when the hardware RS-232 receives a byte of data. Once two bytes of data are received (int16), the interrupt reassembles them into a single int16 and calls CalculateAndLaunch().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 78, 16);&lt;br /&gt;
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);     //Counter used for Encoder A -- Up Count&lt;br /&gt;
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);     //Counter used for Encoder B -- Down Count&lt;br /&gt;
&lt;br /&gt;
   //setup offsets and intialize encoders&lt;br /&gt;
   upCount = get_timer0();&lt;br /&gt;
   downCount = get_timer1();&lt;br /&gt;
   lastUpCount = upCount;&lt;br /&gt;
   lastDownCount = downCount;&lt;br /&gt;
  &lt;br /&gt;
   encoderActual += (upCount - downCount);&lt;br /&gt;
 &lt;br /&gt;
   initialCount = encoderActual;&lt;br /&gt;
 &lt;br /&gt;
   offset = encoderActual%EncCount;&lt;br /&gt;
   if(encoderActual &amp;lt; 0) offset = -offset;&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   ext_int_edge(0, H_TO_L);      // interrupt on INT0/RB0 pin, low to high transition&lt;br /&gt;
   setup_ccp1(CCP_PWM);&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(0);&lt;br /&gt;
   output_low(PIN_C4);&lt;br /&gt;
   delay_us(10);&lt;br /&gt;
 &lt;br /&gt;
   while(TRUE) {&lt;br /&gt;
      delay_ms(5000);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
== Distance Calculation ==&lt;br /&gt;
Shot distance was based on a second order polynomial fit we obtained experimentally. The data we collected is shown in the image on the right. [[Image:Distance-Calibration-basketball.png | Calibration data and trendline | thumb | 300px | right]]&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Y466dzP-qiY Link To Video]&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12914</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12914"/>
		<updated>2009-03-20T08:14:26Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* PD Controller */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two PICs communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
We used two PICs for this project. One ran the motor control since we wanted the smallest interrupt possible for the most accurate speed control. The other PIC ran the servo attached to the turntable as well as the infrared and ultrasonic sensors.&lt;br /&gt;
 &lt;br /&gt;
The motor was controlled using a PD controller which controlled both speed and position. Theory behind the controller was that if accurate speed control could be achieved along with the ability to control the release point by stopping the motor, we could control the distance the ball traveled to a high degree of accuracy having it follow simple kinematic equations. The launch was triggered when the ultrasonic sensor distance was sent to it. We opted against I2C and instead went with RS-232 for simplicity since we were only sending two bytes of data.&lt;br /&gt;
&lt;br /&gt;
Full source code of the motor controller can be found [[Media:Motor-Control.c|here]].&lt;br /&gt;
&lt;br /&gt;
== PD Controller ==&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; &lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount;&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
We used hardware encoders due to the speed of rotation of the shaft.&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
Theta was used for position control. Due to the way we implemented it, the motor was only was only allowed 359.9 degrees of rotation which was suitable for our launching arm.&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
A positive thetaError indicated that the motor needed to move CCW to reach its destination A negative thetaError indicated that the motor needed to move CW to reach its destination.&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
 &lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
The encoderTargetTheta was used to handle the case of overshoots and was the theta value of the encoderTarget after the speed was added. If that theta value was above/below (depending on direction) the target theta value, it represented that the input had reached its destination, so the speed drops to zero, and the encoderTarget is set to the correct target value.&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
In tuning the PD controller, it was found that different speeds needed different tunings in order to receive a smooth and accurate response. These values represent the best values we were able to obtain in tuning.&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
Set PWM values to make motor go forward or reverse. Also, the case where &amp;#039;launching==1&amp;#039; is to return the arm to a loading position after the arm has shot a ball.&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Set the motor&amp;#039;s PWM and check for maximum and minimum values. 624 was used instead of 78 for PWM values based on how we set up our timer2.&lt;br /&gt;
&lt;br /&gt;
== PIC to PIC communication with RS-232 ==&lt;br /&gt;
We choose to use RS-232 to communicate between PICs because of the small amount of data we were sending (a single int16) and to avoid the overhead required by I2C. We accomplished this by breaking our values into 8-bit chunks cast as chars and sending them one at a time.&lt;br /&gt;
&lt;br /&gt;
 sendDistance = avgdistance*100; //distance in cm\&lt;br /&gt;
 &lt;br /&gt;
 //Break distance into two 8-bit ints and cast as chars to send over RS-232&lt;br /&gt;
 //Will be reassembled on other pic&lt;br /&gt;
 putc((char)(sendDistance&amp;gt;&amp;gt;8));&lt;br /&gt;
 putc((char)(sendDistance &amp;amp; 255));&lt;br /&gt;
Code to send value.&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
This interrupt is called when the hardware RS-232 receives a byte of data. Once two bytes of data are received (int16), the interrupt reassembles them into a single int16 and calls CalculateAndLaunch().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 78, 16);&lt;br /&gt;
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);     //Counter used for Encoder A -- Up Count&lt;br /&gt;
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);     //Counter used for Encoder B -- Down Count&lt;br /&gt;
&lt;br /&gt;
   //setup offsets and intialize encoders&lt;br /&gt;
   upCount = get_timer0();&lt;br /&gt;
   downCount = get_timer1();&lt;br /&gt;
   lastUpCount = upCount;&lt;br /&gt;
   lastDownCount = downCount;&lt;br /&gt;
  &lt;br /&gt;
   encoderActual += (upCount - downCount);&lt;br /&gt;
 &lt;br /&gt;
   initialCount = encoderActual;&lt;br /&gt;
 &lt;br /&gt;
   offset = encoderActual%EncCount;&lt;br /&gt;
   if(encoderActual &amp;lt; 0) offset = -offset;&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   ext_int_edge(0, H_TO_L);      // interrupt on INT0/RB0 pin, low to high transition&lt;br /&gt;
   setup_ccp1(CCP_PWM);&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(0);&lt;br /&gt;
   output_low(PIN_C4);&lt;br /&gt;
   delay_us(10);&lt;br /&gt;
 &lt;br /&gt;
   while(TRUE) {&lt;br /&gt;
      delay_ms(5000);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
== Distance Calculation ==&lt;br /&gt;
Shot distance was based on a second order polynomial fit we obtained experimentally. The data we collected is shown in the image on the right. [[Image:Distance-Calibration-basketball.png]]&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Y466dzP-qiY Link To Video]&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12905</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12905"/>
		<updated>2009-03-20T07:31:22Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two PICs communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
We used two PICs for this project. One ran the motor control since we wanted the smallest interrupt possible for the most accurate speed control. The other PIC ran the servo attached to the turntable as well as the infrared and ultrasonic sensors.&lt;br /&gt;
 &lt;br /&gt;
The motor was controlled using a PD controller which controlled both speed and position. Theory behind the controller was that if accurate speed control could be achieved along with the ability to control the release point by stopping the motor, we could control the distance the ball traveled to a high degree of accuracy having it follow simple kinematic equations. The launch was triggered when the ultrasonic sensor distance was sent to it. We opted against I2C and instead went with RS-232 for simplicity since we were only sending two bytes of data.&lt;br /&gt;
&lt;br /&gt;
Full source code of the motor controller can be found [[Media:Motor-Control.c|here]].&lt;br /&gt;
&lt;br /&gt;
== PD Controller ==&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; //NEW HERE (REMOVED (SIGNED INT16 CAST)&lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount; //NEW HERE SAME AS ABOVE&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
&lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
This interrupt is called when the hardware RS-232 receives a byte of data. Once two bytes of data are received (int16), the interrupt reassembles them into a single int16 and calls CalculateAndLaunch().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 78, 16);&lt;br /&gt;
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);     //Counter used for Encoder A -- Up Count&lt;br /&gt;
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);     //Counter used for Encoder B -- Down Count&lt;br /&gt;
&lt;br /&gt;
   //setup offsets and intialize encoders&lt;br /&gt;
   upCount = get_timer0();&lt;br /&gt;
   downCount = get_timer1();&lt;br /&gt;
   lastUpCount = upCount;&lt;br /&gt;
   lastDownCount = downCount;&lt;br /&gt;
  &lt;br /&gt;
   encoderActual += (upCount - downCount);&lt;br /&gt;
 &lt;br /&gt;
   initialCount = encoderActual;&lt;br /&gt;
 &lt;br /&gt;
   offset = encoderActual%EncCount;&lt;br /&gt;
   if(encoderActual &amp;lt; 0) offset = -offset;&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   ext_int_edge(0, H_TO_L);      // interrupt on INT0/RB0 pin, low to high transition&lt;br /&gt;
   setup_ccp1(CCP_PWM);&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(0);&lt;br /&gt;
   output_low(PIN_C4);&lt;br /&gt;
   delay_us(10);&lt;br /&gt;
 &lt;br /&gt;
   while(TRUE) {&lt;br /&gt;
      delay_ms(5000);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Y466dzP-qiY Link To Video]&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12904</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12904"/>
		<updated>2009-03-20T07:18:22Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two PICs communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
We used two PICs for this project. One ran the motor control since we wanted the smallest interrupt possible for the most accurate speed control. The other PIC ran the servo attached to the turntable as well as the infrared and ultrasonic sensors.&lt;br /&gt;
 &lt;br /&gt;
The motor was controlled using a PD controller which controlled both speed and position. Theory behind the controller was that if accurate speed control could be achieved along with the ability to control the release point by stopping the motor, we could control the distance the ball traveled to a high degree of accuracy having it follow simple kinematic equations. The launch was triggered when the ultrasonic sensor distance was sent to it. We opted against I2C and instead went with RS-232 for simplicity since we were only sending two bytes of data.&lt;br /&gt;
&lt;br /&gt;
Full source code of the motor controller can be found [[Media:Motor-Control.c|here]].&lt;br /&gt;
&lt;br /&gt;
== PD Controller ==&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; //NEW HERE (REMOVED (SIGNED INT16 CAST)&lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount; //NEW HERE SAME AS ABOVE&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
&lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
This interrupt is called when the hardware RS-232 receives a byte of data. Once two bytes of data are received (int16), the interrupt reassembles them into a single int16 and calls CalculateAndLaunch().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 78, 16);&lt;br /&gt;
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);     //Counter used for Encoder A -- Up Count&lt;br /&gt;
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);     //Counter used for Encoder B -- Down Count&lt;br /&gt;
&lt;br /&gt;
   //setup offsets and intialize encoders&lt;br /&gt;
   upCount = get_timer0();&lt;br /&gt;
   downCount = get_timer1();&lt;br /&gt;
   lastUpCount = upCount;&lt;br /&gt;
   lastDownCount = downCount;&lt;br /&gt;
  &lt;br /&gt;
   encoderActual += (upCount - downCount);&lt;br /&gt;
 &lt;br /&gt;
   initialCount = encoderActual;&lt;br /&gt;
 &lt;br /&gt;
   offset = encoderActual%EncCount;&lt;br /&gt;
   if(encoderActual &amp;lt; 0) offset = -offset;&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   ext_int_edge(0, H_TO_L);      // interrupt on INT0/RB0 pin, low to high transition&lt;br /&gt;
   setup_ccp1(CCP_PWM);&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(0);&lt;br /&gt;
   output_low(PIN_C4);&lt;br /&gt;
   delay_us(10);&lt;br /&gt;
 &lt;br /&gt;
   while(TRUE) {&lt;br /&gt;
      delay_ms(5000);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
LINK TO VIDEO HERE&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12883</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12883"/>
		<updated>2009-03-20T06:40:44Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two pics communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
We used two PICs for this project. One ran the motor control since we wanted the smallest interrupt possible for the most accurate speed control. The other PIC ran the servo attached to the turntable as well as the infrared and ultrasonic sensors.&lt;br /&gt;
 &lt;br /&gt;
The motor was controlled using a PD controller which controlled both speed and position. Theory behind the controller was that if accurate speed control could be achieved along with the ability to control the release point by stopping the motor, we could control the distance the ball traveled to a high degree of accuracy having it follow simple kinematic equations. The launch was triggered when the ultrasonic sensor distance was sent to it. We opted against I2C and instead went with RS-232 for simplicity since we were only sending two bytes of data.&lt;br /&gt;
&lt;br /&gt;
Full source code of the motor controller can be found here:[[Media:Motor-Control.c]].&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
This interrupt is called when the hardware RS-232 receives a byte of data. Once two bytes of data are received (int16), the interrupt reassembles them into a single int16 and calls CalculateAndLaunch().&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; //NEW HERE (REMOVED (SIGNED INT16 CAST)&lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount; //NEW HERE SAME AS ABOVE&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
&lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 78, 16);&lt;br /&gt;
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);     //Counter used for Encoder A -- Up Count&lt;br /&gt;
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);     //Counter used for Encoder B -- Down Count&lt;br /&gt;
&lt;br /&gt;
   //setup offsets and intialize encoders&lt;br /&gt;
   upCount = get_timer0();&lt;br /&gt;
   downCount = get_timer1();&lt;br /&gt;
   lastUpCount = upCount;&lt;br /&gt;
   lastDownCount = downCount;&lt;br /&gt;
  &lt;br /&gt;
   encoderActual += (upCount - downCount);&lt;br /&gt;
 &lt;br /&gt;
   initialCount = encoderActual;&lt;br /&gt;
 &lt;br /&gt;
   offset = encoderActual%EncCount;&lt;br /&gt;
   if(encoderActual &amp;lt; 0) offset = -offset;&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   ext_int_edge(0, H_TO_L);      // interrupt on INT0/RB0 pin, low to high transition&lt;br /&gt;
   setup_ccp1(CCP_PWM);&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(0);&lt;br /&gt;
   output_low(PIN_C4);&lt;br /&gt;
   delay_us(10);&lt;br /&gt;
 &lt;br /&gt;
   while(TRUE) {&lt;br /&gt;
      delay_ms(5000);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
LINK TO VIDEO HERE&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Turntable-Control.c&amp;diff=12856</id>
		<title>File:Turntable-Control.c</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Turntable-Control.c&amp;diff=12856"/>
		<updated>2009-03-20T06:17:27Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Motor-Control.c&amp;diff=12855</id>
		<title>File:Motor-Control.c</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Motor-Control.c&amp;diff=12855"/>
		<updated>2009-03-20T06:17:04Z</updated>

		<summary type="html">&lt;p&gt;John Rula: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12832</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12832"/>
		<updated>2009-03-20T06:01:24Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two pics communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay(clock=40000000)&lt;br /&gt;
 #use rs232(baud=19200, UART1)&lt;br /&gt;
&lt;br /&gt;
 int16 EncCount = 9984;           //Number of Encoder Counts per Rev&lt;br /&gt;
 float pGain =1.25;               //Kp for proportional control&lt;br /&gt;
 float dGain =3;                  //Kd for derivative control&lt;br /&gt;
 signed int32 encoderTarget = 0;  //Target for encoder counts to reach&lt;br /&gt;
 signed int32 error = 0;          //EncoderTarget - EncoderActual&lt;br /&gt;
 signed int32 lastError;          //Previous error term&lt;br /&gt;
 signed int32 encoderActual = 0;  //Actual position of shaft in total encoder counts&lt;br /&gt;
 signed int32 initialCount = 0;   //Encoder count when system boots&lt;br /&gt;
 signed int32 speed = 0;          //Speed of rotation 250*speed = encoder counts per second&lt;br /&gt;
 signed int32 targetSpeed = 0;    //What speed should be set to&lt;br /&gt;
 signed int32 Torque;             //PWM value&lt;br /&gt;
 signed int32 derivative = 0;     //Derivative term&lt;br /&gt;
 signed int32 offset = 0;         //Value to set theta = 0 from when system starts&lt;br /&gt;
 int16 theta=0;                   //Value between 0-&amp;gt;EncCount representing angle from 0 to 360&lt;br /&gt;
 int16 thetaTarget = 0;           //Position Control Target&lt;br /&gt;
 int16 encoderTargetTheta =0 ;    //Theta value of encoderTarget after speed has been added&lt;br /&gt;
 signed int32 thetaError = 0;     // == thetaTarget - theta&lt;br /&gt;
 int16 upCount = 0, downCount = 0, lastUpCount = 0, lastDownCount = 0;  //Encoder count variables&lt;br /&gt;
 int launching = 0;               //Indicates whether arm is on up-swing of launch (1), (0) otherwise&lt;br /&gt;
 int32 milsecs = 0;               //Increments at each interrupt&lt;br /&gt;
 int rsCount = 0;                 //Used to track characters coming over RS-232&lt;br /&gt;
 char c_0 = 0;&lt;br /&gt;
 char c_1 = 0;&lt;br /&gt;
 int16 distance =0;               //Distance sent to PIC over RS-232&lt;br /&gt;
 float shotSpeed;                 //Speed determined by CalculateAndLaunch()&lt;br /&gt;
&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle);&lt;br /&gt;
 void CalculateAndLaunch(float dist);&lt;br /&gt;
&lt;br /&gt;
 #INT_RDA&lt;br /&gt;
 void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
    if(kbhit()) {&lt;br /&gt;
       if(rsCount == 0) c_0 = getc();&lt;br /&gt;
       else if(rsCount == 1) {&lt;br /&gt;
          c_1 = getc();&lt;br /&gt;
          distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
          CalculateAndLaunch((float)distance);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    rsCount++;&lt;br /&gt;
    if(rsCount &amp;gt;= 2) rsCount = 0;  &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 #INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
 void Timer2isr() {&lt;br /&gt;
   milsecs++;&lt;br /&gt;
   if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; //NEW HERE (REMOVED (SIGNED INT16 CAST)&lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount; //NEW HERE SAME AS ABOVE&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
&lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
&lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
&lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         Torque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         Torque = 1.25 * error + 3 * derivative;     &lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         Torque = 2 * error + 6 * derivative;     &lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         Torque = pGain * error + dGain * derivative;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
         //invert for PWM&lt;br /&gt;
         Torque = 624 + Torque;&lt;br /&gt;
         output_high(PIN_C4);&lt;br /&gt;
         if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
             launching = 0;&lt;br /&gt;
             thetaTarget = 300;&lt;br /&gt;
             targetSpeed = 10;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if(Torque &amp;lt; 0) Torque = 0;&lt;br /&gt;
     if(Torque &amp;gt; 624) Torque = 624;&lt;br /&gt;
     set_pwm1_duty(Torque);&lt;br /&gt;
    &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void main() {&lt;br /&gt;
&lt;br /&gt;
   setup_timer_2(T2_DIV_BY_4, 78, 16);&lt;br /&gt;
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);     //Counter used for Encoder A -- Up Count&lt;br /&gt;
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);     //Counter used for Encoder B -- Down Count&lt;br /&gt;
&lt;br /&gt;
   //setup offsets and intialize encoders&lt;br /&gt;
   upCount = get_timer0();&lt;br /&gt;
   downCount = get_timer1();&lt;br /&gt;
   lastUpCount = upCount;&lt;br /&gt;
   lastDownCount = downCount;&lt;br /&gt;
  &lt;br /&gt;
   encoderActual += (upCount - downCount);&lt;br /&gt;
 &lt;br /&gt;
   initialCount = encoderActual;&lt;br /&gt;
 &lt;br /&gt;
   offset = encoderActual%EncCount;&lt;br /&gt;
   if(encoderActual &amp;lt; 0) offset = -offset;&lt;br /&gt;
&lt;br /&gt;
   enable_interrupts(INT_TIMER2);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
   ext_int_edge(0, H_TO_L);      // interrupt on INT0/RB0 pin, low to high transition&lt;br /&gt;
   setup_ccp1(CCP_PWM);&lt;br /&gt;
&lt;br /&gt;
   set_pwm1_duty(0);&lt;br /&gt;
   output_low(PIN_C4);&lt;br /&gt;
   delay_us(10);&lt;br /&gt;
 &lt;br /&gt;
   while(TRUE) {&lt;br /&gt;
      delay_ms(5000);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
    targetSpeed = speed;&lt;br /&gt;
    thetaTarget = angle;&lt;br /&gt;
    launching=1;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 void CalculateAndLaunch(float dist) {&lt;br /&gt;
    dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
    shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
    LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
LINK TO VIDEO HERE&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12783</id>
		<title>Basketball</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Basketball&amp;diff=12783"/>
		<updated>2009-03-20T05:34:42Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Mechatronics2009Bball|right|thumb|180px]]&lt;br /&gt;
&amp;lt;br=clear all&amp;gt;&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[image:Team_12_Mechatronics_2009|Team Members from right to left: John, Alex, and Meredith|thumb|250px|right]]&lt;br /&gt;
* John Rula (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Alex Wojcicki (Mechanical Engineering, Class of 2009)&lt;br /&gt;
* Meredith Chow (Electrical Engineering, Class of 2010)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
A throwing arm propelled by a Pittman DC brush motor is mounted on a turntable and throws the ball into the &amp;quot;hoop.&amp;quot; The hoop is wrapped in reflective tape and an IR emitter, receiver pair is used to sense where the IR is reflected most (the hoop with highly reflective tape). An ultrasonic sensor then pings the hoop for the distance of the hoop. With this information, the arm is able to &amp;quot;make a basket.&amp;quot;&lt;br /&gt;
[[Image:Mechatronics2009Bball|Entire system|left|thumb|200px]][[Image:mech2009bballcloseup|Front view|left|thumb|200px]][[Image:mech2009bballcloseupalternate|Close up|left|thumb|350px]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:Mechatronics2009BballCADassembly|CAD assembly|right|thumb|250px]]&lt;br /&gt;
The major mechanical components were machined out of clear acrylic using the laser cutter in the machine shop. Holes were machined and threaded as required. The base is a square (12&amp;quot; x 12&amp;quot;) with threaded holes for attachment to the purchased turntable bearing. The turntable has threaded holes for attachment to the turntable bearing as well. Large holes were added to the turntable for screw access during assembly because once one of the parts is attached to the turntable, the screws would otherwise not be able to be tightened. The turntable features a rectangular cutout for the servo motor and threaded holes for mounting. There are additional through holes for mounting the sensor bracket and the motor supports.&lt;br /&gt;
&lt;br /&gt;
Two motor supports were designed to accept the Pittman motor and hold it six inches above the turntable surface. Fasteners are inserted from below the turntable into threaded holes in the motor supports. Clamps were designed to thread onto the supports and secure the motor in place. The sensors (IR emitter/receiver pair and ultrasonic sensor) are mounted on a machined acrylic bracket that which is attached to the turntable again through fasteners inserted underneath the turntable. &lt;br /&gt;
&lt;br /&gt;
The arm is also made of laser cut acrylic. It was designed with a close fit on the flat of the motor shaft and with a clamp for tightening using a threaded fastener. For manufacturing reasons, the ball holding portion of the arm was cut out of a separate piece of acrylic and secured to the end of the throwing arm.&lt;br /&gt;
&lt;br /&gt;
The hoop can be anything with the highly reflective tape around it. It is suggested to have a circular profile for better performance detecting its center using the IR emitter/receiver.&lt;br /&gt;
[[Image:Mechatronics2009BballArmCloseup|Throwing arm attachment close up|right|thumb|250px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Components ===&lt;br /&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;Pittman Motor &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;GM8712&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;RC Servo Motor - Futaba &amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Acrylic .25&amp;quot; Thick, 24&amp;quot;X 24&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8560K357&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#8560K357 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$39.63&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Corrosion-Resistant Turntable&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;6031K17&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.mcmaster.com/#6031k17 McMaster]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;$2.42&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Fasteners&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;24&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Shop supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Rubber Feet&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
The IR pair, ultrasonic, and servo have a relatively simple circuit. In the diagram below, the IR pair, ultrasonic, and servo are controlled by the program on PIC1. The IR pair and ultrasonic sensor are stacked vertically and inserted into the fitted holes on the laser cut acrylic. Because of the close proximity of the IR pair, to prevent saturation of the IR receiver, the emitter was wrapped in electrical tape. This allowed for the detection of reflected IR rather than from the emitter right below the detector. The RC servo goes through a sweep looking for the hoop. It finds the hoop by storing the location of the highest IR detection. The reflective tape used in Design Challenge 2008 and 2009 was used to wrap the hoop and is used to assist in the finding of the hoop as it reflects more IR radiation than most common objects. After making its sweep, the servo returns to the position where the most IR was detected. The ultrasonic sensor will then ping the hoop to find the distance of the hoop.&lt;br /&gt;
&lt;br /&gt;
The Pittman motor, H-Bridge, and encoder chip circuit is more complex. This circuit is run by PIC2. The information collected about the hoop location is communicated from PIC1 to PIC2. The Pittman is used to launch the ball. After the hoop is found, the arm attached to the Pittman launches the ball into the hoop. The shaft rotates forward and then reverses to its previous position. The device is then ready to find the hoop and launch the ball again. &lt;br /&gt;
&lt;br /&gt;
The two pics communicated with a common ground and wire connecting RC6 and RC7 as shown in the diagram. The power supply was two 12 volt power supplies connected in series to give a total of 24 volts.&lt;br /&gt;
&lt;br /&gt;
=== Electrical Components ===&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;PICs&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;PIC18F4520&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Encoder&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LS7083&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;H-Bridge&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;L298N&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Ping Ultrasonic Sensor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;28015&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab 5 supply&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Emitter&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;QED123&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;IR Phototransistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;LTR-4206E&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Diodes&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;1N4148&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Resistors&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;47.5/150K&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Lab&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;-&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[image:team12mech2009cktwiki|Circuit diagram of how the the pics, sensors, and motor components are connected.|thumb|500px|left]][[image:mech2009bballelectronics|How the the pics, sensors, and motor components are connected.|thumb|500px|left]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=19200, UART1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int16 EncCount = 9984;&lt;br /&gt;
float pGain =1.25;&lt;br /&gt;
float dGain =3;&lt;br /&gt;
signed int32 encoderTarget = 0;&lt;br /&gt;
signed int32 error = 0;&lt;br /&gt;
signed int32 lastError;&lt;br /&gt;
signed int32 encoderActual = 0;&lt;br /&gt;
signed int32 initialCount = 0;&lt;br /&gt;
signed int32 speed = 0;&lt;br /&gt;
signed int32 targetSpeed = 0;&lt;br /&gt;
signed int32 LeftError, LeftErrorLastTime=0, LeftIntegral, LeftDerivative, LeftTorque;&lt;br /&gt;
signed int32 derivative = 0;&lt;br /&gt;
signed int32 offset = 0;&lt;br /&gt;
int16 theta=0;&lt;br /&gt;
int16 thetaTarget = 0;&lt;br /&gt;
int16 encoderTargetTheta =0 ;&lt;br /&gt;
signed int32 thetaError = 0;&lt;br /&gt;
int16 upCount = 0, downCount = 0, lastUpCount = 0, lastDownCount = 0;&lt;br /&gt;
int launching = 0;&lt;br /&gt;
int32 milsecs = 0;&lt;br /&gt;
int rsCount = 0;&lt;br /&gt;
char c_0 = 0;&lt;br /&gt;
char c_1 = 0;&lt;br /&gt;
int16 distance =0 ;&lt;br /&gt;
float shotSpeed;&lt;br /&gt;
&lt;br /&gt;
void LaunchBall(int16 speed, int16 angle);&lt;br /&gt;
void CalculateAndLaunch(float dist);&lt;br /&gt;
&lt;br /&gt;
#INT_RDA&lt;br /&gt;
void INTRDAisr() {&lt;br /&gt;
  &lt;br /&gt;
   if(kbhit()) {&lt;br /&gt;
      if(rsCount == 0) c_0 = getc();&lt;br /&gt;
      else if(rsCount == 1) {&lt;br /&gt;
         c_1 = getc();&lt;br /&gt;
         distance = (int16)c_1 + ((int16)c_0&amp;lt;&amp;lt;8);&lt;br /&gt;
         CalculateAndLaunch((float)distance);&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
  &lt;br /&gt;
   rsCount++;&lt;br /&gt;
   if(rsCount &amp;gt;= 2) rsCount = 0;&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer3 overflows&lt;br /&gt;
void Timer2isr() {&lt;br /&gt;
  milsecs++;&lt;br /&gt;
  if ((milsecs &amp;amp; 7) == 0) {      // servo routine every 4ms is plenty.  250x/sec&lt;br /&gt;
&lt;br /&gt;
     //update counters and encoder&lt;br /&gt;
     upCount = get_timer0();&lt;br /&gt;
     encoderActual += upCount - lastUpCount; //NEW HERE (REMOVED (SIGNED INT16 CAST)&lt;br /&gt;
     downCount = get_timer1();&lt;br /&gt;
     encoderActual -= downCount - lastDownCount; //NEW HERE SAME AS ABOVE&lt;br /&gt;
&lt;br /&gt;
     lastUpCount = upCount;&lt;br /&gt;
     lastDownCount = downCount;&lt;br /&gt;
    &lt;br /&gt;
     theta = (int16)(encoderActual - offset) % EncCount;&lt;br /&gt;
     thetaError = (signed int32)thetaTarget- (signed int32)theta;&lt;br /&gt;
    &lt;br /&gt;
     //speed controls whether it is in forward or reverse&lt;br /&gt;
     if(thetaError &amp;gt; 0) speed = targetSpeed;&lt;br /&gt;
     else if(thetaError &amp;lt; 0) speed = -targetSpeed;&lt;br /&gt;
&lt;br /&gt;
     encoderTarget += speed; //need to add accuracy to speed&lt;br /&gt;
    &lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
    &lt;br /&gt;
     if(encoderTargetTheta &amp;gt; thetaTarget &amp;amp;&amp;amp; speed &amp;gt; 0) {&lt;br /&gt;
        encoderTarget -= encoderTargetTheta - thetaTarget;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
&lt;br /&gt;
     } else if(encoderTargetTheta &amp;lt; thetaTarget &amp;amp;&amp;amp; speed &amp;lt; 0) {&lt;br /&gt;
        encoderTarget += thetaTarget - encoderTargetTheta;&lt;br /&gt;
        targetSpeed = 0;&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     encoderTargetTheta = (int16)(encoderTarget) % EncCount;&lt;br /&gt;
    &lt;br /&gt;
     //do calculations for PD controller with new error&lt;br /&gt;
     error = encoderTarget - (encoderActual - initialCount);&lt;br /&gt;
&lt;br /&gt;
     derivative = error - lastError;&lt;br /&gt;
     lastError = error;&lt;br /&gt;
    &lt;br /&gt;
     //At different speeds, need different gains, higher kps and kds for higher speeds ect...&lt;br /&gt;
     if(speed &amp;lt;= 5) {&lt;br /&gt;
         LeftTorque = 3*error + 2*derivative;&lt;br /&gt;
     } else&lt;br /&gt;
     if (speed &amp;lt;= 75) {&lt;br /&gt;
         LeftTorque = 1.25 * error + 3 * derivative;     // good luck w/o floats...&lt;br /&gt;
     } else if (speed &amp;lt;= 100) {&lt;br /&gt;
         LeftTorque = 2 * error + 6 * derivative;     // good luck w/o floats...&lt;br /&gt;
     } else {  //speed &amp;gt; 100&lt;br /&gt;
         LeftTorque = pGain * error + dGain * derivative;     // good luck w/o floats...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if(error &amp;gt; 0) {   //going in the CCW direction, Left torque positive&lt;br /&gt;
         output_low(PIN_C4);&lt;br /&gt;
     }&lt;br /&gt;
     else if(error &amp;lt; 0) {&lt;br /&gt;
        //invert for PWM&lt;br /&gt;
        LeftTorque = 624 + LeftTorque;&lt;br /&gt;
        output_high(PIN_C4);&lt;br /&gt;
        if(launching == 1 &amp;amp;&amp;amp; thetaError &amp;lt; 0) { //used to tune when launching&lt;br /&gt;
            launching = 0;&lt;br /&gt;
            thetaTarget = 300;&lt;br /&gt;
            targetSpeed = 10;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
       &lt;br /&gt;
     if(LeftTorque &amp;lt; 0) LeftTorque = 0;&lt;br /&gt;
     if(LeftTorque &amp;gt; 624) LeftTorque = 624;&lt;br /&gt;
    &lt;br /&gt;
     set_pwm1_duty(LeftTorque);&lt;br /&gt;
&lt;br /&gt;
     output_d(encoderActual);&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
  setup_timer_2(T2_DIV_BY_4, 78, 16);        // clock at 16KHz, interrupt every 4*25nS * 4 * 78 * 16 = 0.5mS&lt;br /&gt;
&lt;br /&gt;
  setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);     // default is divide by two!&lt;br /&gt;
  setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);     // default is divide by one&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  //setup offsets and intialize encoders&lt;br /&gt;
  upCount = get_timer0();&lt;br /&gt;
  downCount = get_timer1();&lt;br /&gt;
  lastUpCount = upCount;&lt;br /&gt;
  lastDownCount = downCount;&lt;br /&gt;
&lt;br /&gt;
  encoderActual += (upCount - downCount);&lt;br /&gt;
&lt;br /&gt;
  initialCount = encoderActual;&lt;br /&gt;
&lt;br /&gt;
  offset = encoderActual%EncCount;&lt;br /&gt;
  if(encoderActual &amp;lt; 0) offset = -offset;&lt;br /&gt;
&lt;br /&gt;
  enable_interrupts(INT_TIMER2);&lt;br /&gt;
  enable_interrupts(INT_RDA);&lt;br /&gt;
  enable_interrupts(GLOBAL);&lt;br /&gt;
 &lt;br /&gt;
  ext_int_edge(0, H_TO_L);      // interrupt on INT0/RB0 pin, low to high transition&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  setup_ccp1(CCP_PWM);&lt;br /&gt;
  set_pwm1_duty(0);&lt;br /&gt;
  delay_us(10);&lt;br /&gt;
&lt;br /&gt;
  output_low(PIN_C4);&lt;br /&gt;
&lt;br /&gt;
  while(TRUE) {&lt;br /&gt;
     delay_ms(5000);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void LaunchBall(int16 speed, int16 angle) {&lt;br /&gt;
   targetSpeed = speed;&lt;br /&gt;
   thetaTarget = angle;&lt;br /&gt;
   launching=1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void CalculateAndLaunch(float dist) {&lt;br /&gt;
      dist = dist+30; //adjust for distance between ranger and motor&lt;br /&gt;
      shotSpeed = -0.0012*(dist*dist) + 0.5884*dist + 89.678;&lt;br /&gt;
      LaunchBall((int16)(shotSpeed/2), 3000);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
In the end, the project ultimately succeeded -- baskets could be made. However, better tuning for the motor control and needs to be developed for more consistent results. &lt;br /&gt;
&lt;br /&gt;
LINK TO VIDEO HERE&lt;br /&gt;
&lt;br /&gt;
===Problems Encountered===&lt;br /&gt;
&lt;br /&gt;
*Attempting to integrate multiple pics and circuits onto one circuit board did not give good results. Ultimately, we had to use separate boards for each pic. This could be due to the effect of motor noise on our control circuitry.&lt;br /&gt;
&lt;br /&gt;
*Motor control was an intense programming effort -- almost a project in its own right. Trying to combine the motor control and calibrate our throwing distance was difficult. Designing a functioning throwing device along with getting the rest of the project implemented was difficult to complete with the given time constraints.&lt;br /&gt;
&lt;br /&gt;
*Many components burned out. Fly back diodes were implemented however, we still went through quite a few H-bridges. Encoder chips also burned out. The PING sensor burned out as well. We are not sure of the cause of some of these part failures.&lt;br /&gt;
&lt;br /&gt;
*The length of wires for the Encoder A and B should be limited. When using long wires running from the encoder, we were not able to get our encoder chip to function properly. Replacing them with shorter wires fixed the issue. Because the signal from the encoder is switching at such high speeds, the loss in the long wires played a significant effect resulting in a faulty encoder count. Larger diameter wires may be an alternate solution to this problem.&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
A few things we might change if we did it again:&lt;br /&gt;
*Simplify the motor control portion of the project. Trying to implement a speed control using the encoder count was difficult to implement. Simply using PWM to drive the motor at different speeds may have been sufficient.&lt;br /&gt;
*Test different wires for length and diameter for optimal performance for the Encoder A and B connections.&lt;br /&gt;
*Combine the PICs on one circuit board, solving the issues we encountered when attempting this.&lt;br /&gt;
*Perform a more detailed calibration, adjusting starting position, final launching position, and speed to get improved control over throwing distance.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Fingertip_laser_light_sensor&amp;diff=10704</id>
		<title>Fingertip laser light sensor</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Fingertip_laser_light_sensor&amp;diff=10704"/>
		<updated>2009-02-12T18:32:12Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Circuit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
I will provide you with a laser that emits a sheet of laser light and a phototransistor for detecting this light.  You will investigate their use in developing a fingertip position sensor that senses distance to the finger based on reflected laser light.  Your job is to design a sensor circuit and determine the analog voltage readings you get as a function of (1) your finger position and (2) the sensor&amp;#039;s location relative to the emitter.  You will likely display your results by communicating with a PC or by writing to an LCD (see, e.g., [[C Example: Serial LCD]] or [[C Example: Parallel Interfacing with LCDs]]).&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:Setup.jpg|thumb|right|250px|Experimental Setup]]&lt;br /&gt;
A laser that emits a sheet of laser light and phototransistor were the main components of this lab. They are used to investigate a fingertip position sensor that senses the position of the finger based on reflected laser light. The laser is positioned so that it emits a sheet of light just above the plane of the table. If a finger is placed within this field of light, then it will reflect the light back towards the laser. A phototransistor was used to detect the light reflected from the finger. A sensor circuit was designed to take analog voltage readings from the phototransistor with the intention of relating the intensity of reflected light to both the (1) finger position and (2) the phototransistor&amp;#039;s location relative to the emitter. The results were displayed by communicating with a PC.&lt;br /&gt;
&lt;br /&gt;
To begin we placed the phototransistor directly adjacent to the laser in order that the distance from the laser to the finger would be approximately the same as the distance from the finger back to the phototransistor. In our first experimental setup, we tested four different resistors in the phototransistor sensing circuit while varying the finger position directly away from the laser (up/down in the figure) in order to get an idea of the level of sensitivity that each resistor would provide. Our second experiment involved moving the finger perpindicular to the laser (left/right in the figure) at three fixed intervals.&lt;br /&gt;
&lt;br /&gt;
Then, we manipulated the position of the phototransistor to see if we could get an improved sensitivity from our sensing circuit. In our third experiment, we put a shield (electrical tape) on the backside of the phototransistor and moved it directly out (down in the figure) into the sheet of light at different positions and varied the finger position in the same (up/down) direction. In the fourth experiment, we moved the transistor directly to the left of the laser in several positions and measured the variation as the finger moved in the up/down direction.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Important Note: &amp;#039;&amp;#039;&amp;#039;The effect of ambient light on the photodiode is significant. In fact, the shadow cast on the photodiode when a finger was placed nearby had a larger effect than the total light reflected from the finger. In order to compensate for this, it was necessary to strobe the laser. The measurement when the laser was on was compared to the measurement when the laser was off to compensate for the ambient light and determine the light intensity contributed by just the laser. (See Code)&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
[[Image:detector circuit.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
The code involved in the fingertip detector strobes the laser every 10ms to get a reading of both the laser light and the ambient light on the phototransitsor. The ambient light is then subtracted out to give only the amount of laser light reflected. Due to the noise involved in the reading from the phototransistor, we averaged every 20 readings for each output.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #DEVICE ADC=10	//10-bit ADC&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay(clock=40000000)       // 40 MHz crystal on PCB&lt;br /&gt;
 #use rs232(baud=19200, UART1)       // hardware uart &lt;br /&gt;
 int16 reading;&lt;br /&gt;
 int16 ambient;&lt;br /&gt;
 int32 reading_sum=0;&lt;br /&gt;
 int32 ambient_sum=0;&lt;br /&gt;
 int i=0;&lt;br /&gt;
 float dist=0;&lt;br /&gt;
 int16 diff = 0;&lt;br /&gt;
 void main()&lt;br /&gt;
 {&lt;br /&gt;
  setup_adc_ports(AN0_TO_AN3);	//setup ADC ports&lt;br /&gt;
  setup_adc(ADC_CLOCK_INTERNAL);   &lt;br /&gt;
  while(TRUE) {&lt;br /&gt;
     set_adc_channel(0);		//set adc channel&lt;br /&gt;
     output_high(PIN_C0);		//strobe the laser high for 10 ms&lt;br /&gt;
     delay_ms(10);&lt;br /&gt;
     reading = read_adc();		//take phototransistor reading with reflected laser light&lt;br /&gt;
     reading_sum += reading;	//add reading to reading_sum which we will average later&lt;br /&gt;
     output_low(PIN_C0);		//strobe the laser low for 10 ms&lt;br /&gt;
     delay_ms(10);&lt;br /&gt;
     ambient = read_adc();	//take reading of ambient light&lt;br /&gt;
     ambient_sum += ambient;	//add ambient reading to ambient_sum which we will average later&lt;br /&gt;
     i += 1;&lt;br /&gt;
     //Due to the inherent noise of the system, we average 20 readings for each output&lt;br /&gt;
     if(i &amp;gt;= 20) {			//number 20 is number that we average each cycle&lt;br /&gt;
        reading = reading_sum / i;&lt;br /&gt;
        ambient = ambient_sum / i;&lt;br /&gt;
        diff = reading - ambient;&lt;br /&gt;
        dist = 395/(float)diff;		//close approximation of distance curve using 19.5K resistor&lt;br /&gt;
        //print results over the serial port&lt;br /&gt;
        printf(&amp;quot;L = %Lu A = %Lu Diff = %Lu Dist = %f\r\n&amp;quot;, reading, ambient, diff, dist);&lt;br /&gt;
        //reset values of I, reading_sum, and ambient_sum&lt;br /&gt;
        i=0;&lt;br /&gt;
        reading_sum = 0;&lt;br /&gt;
        ambient_sum = 0;&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Data ==&lt;br /&gt;
[[Image:Resistor Selection.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;First Experiment: &amp;#039;&amp;#039;&amp;#039;The phototransistor is placed directly adjacent to the laser. The finger was moved directly away from the laser (up/down in Experimental Setup above). Different resistors were used to investigate sensitivity.&lt;br /&gt;
&lt;br /&gt;
Note: In all experiments voltage was measured on a scale of 0V to 5V and recorded as a 10-bit integer (0-1023). &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Distance Calibration.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
Distance calibration using 19.5 K-Ohm resistor&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The fit applied to the curve was of the form: &amp;lt;math&amp;gt;I=A*d^B&amp;lt;/math&amp;gt;&lt;br /&gt;
where I is the intensity of light (measured as a voltage), d is the distance, and A and B are constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The best fit to the data was A = 395 and B = -1   &amp;lt;math&amp;gt;(R^2=.974)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The resulting calibration used to calculate distance from the intensity is &amp;lt;math&amp;gt;d=I/395&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Varying Horizontal Position.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Second Experiment: &amp;#039;&amp;#039;&amp;#039;The phototransistor is placed directly adjacent to the laser. The finger was placed at fixed distances from the laser (1 cm, 2.5 cm, 5 cm) and then moved horizontally (left/right in Experimental Setup above). Using 19.5 K-Ohm resistor.&lt;br /&gt;
&lt;br /&gt;
Note: The negative values are on the same side of the laser as the phototransistor. This results in a shorter distance for the light to travel and a greater intensity on the left side. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Varying Phototransistor Position.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Third Experiment: &amp;#039;&amp;#039;&amp;#039;The phototransistor was moved directly out into the sheet of light (up/down in Experimental Setup). The finger was moved in same up/down direction. Using 19.5 K-Ohm resistor.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Varying Phototransistor Position Horizontally.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Fourth Experiment: &amp;#039;&amp;#039;&amp;#039;The phototransistor was moved to the left of the laser. The finger was moved in the up/down direction. Using 19.5 K-Ohm Resistor.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Limitations and Environmental Factors ==&lt;br /&gt;
&lt;br /&gt;
There were a few environmental factors that affect the sensors:&lt;br /&gt;
&lt;br /&gt;
1) Ambient light: The overhead light saturated the phototransistor and so the laser was pulsed (the pic was programmed to strobe the laser) in an effort to provide a noticeable difference between the ambient and laser light. As noted above, a finger in front of the transistor cast a shadow which had a larger effect (due to the blocking of the ambient light)than the actual blocking of the laser. Be aware that as the experiment is done any shadow cast on the sensors by a finger or body part will affect the ambient light sensed by the phototransistor and should be taken into account.&lt;br /&gt;
&lt;br /&gt;
2) Lower resistances can be used for the phototransistor to prevent saturation but this also causes a reduced sensitivity to light.&lt;br /&gt;
&lt;br /&gt;
3) The sheet laser provided was not uniform. There were different intensities of light across the line emitted. &lt;br /&gt;
&lt;br /&gt;
4) There is a limited range in which the fingertip laser light sensor is accurate. Using the code and setup described above, there was accurate sensing of the fingertip directly in front of the laser and phototransistor to about seven centimeters.&lt;br /&gt;
&lt;br /&gt;
5) The same finger and the fingernail side were used for all of the experiments. Results may be affected by testing with different fingers or whether it is the fingernail side or not, or a side of the finger. Instead of a finger, a white plastic dowel could be used as a control initially and then a finger used with more progress.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Detector_circuit.jpg&amp;diff=10703</id>
		<title>File:Detector circuit.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Detector_circuit.jpg&amp;diff=10703"/>
		<updated>2009-02-12T18:31:31Z</updated>

		<summary type="html">&lt;p&gt;John Rula: Circuit Diagram&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Circuit Diagram&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Fingertip_laser_light_sensor&amp;diff=10685</id>
		<title>Fingertip laser light sensor</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Fingertip_laser_light_sensor&amp;diff=10685"/>
		<updated>2009-02-12T17:50:28Z</updated>

		<summary type="html">&lt;p&gt;John Rula: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Original Assignment ==&lt;br /&gt;
&lt;br /&gt;
I will provide you with a laser that emits a sheet of laser light and a phototransistor for detecting this light.  You will investigate their use in developing a fingertip position sensor that senses distance to the finger based on reflected laser light.  Your job is to design a sensor circuit and determine the analog voltage readings you get as a function of (1) your finger position and (2) the sensor&amp;#039;s location relative to the emitter.  You will likely display your results by communicating with a PC or by writing to an LCD (see, e.g., [[C Example: Serial LCD]] or [[C Example: Parallel Interfacing with LCDs]]).&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:Setup.jpg|thumb|right|250px|Experimental Setup]]&lt;br /&gt;
A laser that emits a sheet of laser light and phototransistor were the main components of this lab. They are used to investigate a fingertip position sensor that senses the position of the finger based on reflected laser light. The laser is positioned so that it emits a sheet of light just above the plane of the table. If a finger is placed within this field of light, then it will reflect the light back towards the laser. A phototransistor was used to detect the light reflected from the finger. A sensor circuit was designed to take analog voltage readings from the phototransistor with the intention of relating the intensity of reflected light to both the (1) finger position and (2) the phototransistor&amp;#039;s location relative to the emitter. The results were displayed by communicating with a PC.&lt;br /&gt;
&lt;br /&gt;
To begin we placed the phototransistor directly adjacent to the laser in order that the distance from the laser to the finger would be approximately the same as the distance from the finger back to the phototransistor. In our first experimental setup, we tested four different resistors in the phototransistor sensing circuit while varying the finger position directly away from the laser (up/down in the figure) in order to get an idea of the level of sensitivity that each resistor would provide. Our second experiment involved moving the finger perpindicular to the laser (left/right in the figure) at three fixed intervals.&lt;br /&gt;
&lt;br /&gt;
Then, we manipulated the position of the phototransistor to see if we could get an improved sensitivity from our sensing circuit. In our third experiment, we put a shield (electrical tape) on the backside of the phototransistor and moved it directly out (down in the figure) into the sheet of light at different positions and varied the finger position in the same (up/down) direction. In the fourth experiment, we moved the transistor directly to the left of the laser in several positions and measured the variation as the finger moved in the up/down direction.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Important Note: &amp;#039;&amp;#039;&amp;#039;The effect of ambient light on the photodiode is significant. In fact, the shadow cast on the photodiode when a finger was placed nearby had a larger effect than the total light reflected from the finger. In order to compensate for this, it was necessary to strobe the laser. The measurement when the laser was on was compared to the measurement when the laser was off to compensate for the ambient light and determine the light intensity contributed by just the laser. (See Code)&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
The code involved in the fingertip detector strobes the laser every 10ms to get a reading of both the laser light and the ambient light on the phototransitsor. The ambient light is then subtracted out to give only the amount of laser light reflected. Due to the noise involved in the reading from the phototransistor, we averaged every 20 readings for each output.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #DEVICE ADC=10	//10-bit ADC&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay(clock=40000000)       // 40 MHz crystal on PCB&lt;br /&gt;
 #use rs232(baud=19200, UART1)       // hardware uart &lt;br /&gt;
 int16 reading;&lt;br /&gt;
 int16 ambient;&lt;br /&gt;
 int32 reading_sum=0;&lt;br /&gt;
 int32 ambient_sum=0;&lt;br /&gt;
 int i=0;&lt;br /&gt;
 float dist=0;&lt;br /&gt;
 int16 diff = 0;&lt;br /&gt;
 void main()&lt;br /&gt;
 {&lt;br /&gt;
  setup_adc_ports(AN0_TO_AN3);	//setup ADC ports&lt;br /&gt;
  setup_adc(ADC_CLOCK_INTERNAL);   &lt;br /&gt;
  while(TRUE) {&lt;br /&gt;
     set_adc_channel(0);		//set adc channel&lt;br /&gt;
     output_high(PIN_C0);		//strobe the laser high for 10 ms&lt;br /&gt;
     delay_ms(10);&lt;br /&gt;
     reading = read_adc();		//take phototransistor reading with reflected laser light&lt;br /&gt;
     reading_sum += reading;	//add reading to reading_sum which we will average later&lt;br /&gt;
     output_low(PIN_C0);		//strobe the laser low for 10 ms&lt;br /&gt;
     delay_ms(10);&lt;br /&gt;
     ambient = read_adc();	//take reading of ambient light&lt;br /&gt;
     ambient_sum += ambient;	//add ambient reading to ambient_sum which we will average later&lt;br /&gt;
     i += 1;&lt;br /&gt;
     //Due to the inherent noise of the system, we average 20 readings for each output&lt;br /&gt;
     if(i &amp;gt;= 20) {			//number 20 is number that we average each cycle&lt;br /&gt;
        reading = reading_sum / i;&lt;br /&gt;
        ambient = ambient_sum / i;&lt;br /&gt;
        diff = reading - ambient;&lt;br /&gt;
        dist = 395/(float)diff;		//close approximation of distance curve using 19.5K resistor&lt;br /&gt;
        //print results over the serial port&lt;br /&gt;
        printf(&amp;quot;L = %Lu A = %Lu Diff = %Lu Dist = %f\r\n&amp;quot;, reading, ambient, diff, dist);&lt;br /&gt;
        //reset values of I, reading_sum, and ambient_sum&lt;br /&gt;
        i=0;&lt;br /&gt;
        reading_sum = 0;&lt;br /&gt;
        ambient_sum = 0;&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Data ==&lt;br /&gt;
[[Image:Resistor Selection.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;First Experiment: &amp;#039;&amp;#039;&amp;#039;The phototransistor is placed directly adjacent to the laser. The finger was moved directly away from the laser (up/down in Experimental Setup above). Different resistors were used to investigate sensitivity.&lt;br /&gt;
&lt;br /&gt;
Note: In all experiments voltage was measured on a scale of 0V to 5V and recorded as a 10-bit integer (0-1023). &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Distance Calibration.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
Distance calibration using 19.5 K-Ohm resistor&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The fit applied to the curve was of the form: &amp;lt;math&amp;gt;I=A*d^B&amp;lt;/math&amp;gt;&lt;br /&gt;
where I is the intensity of light (measured as a voltage), d is the distance, and A and B are constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The best fit to the data was A = 395 and B = -1   &amp;lt;math&amp;gt;(R^2=.974)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The resulting calibration used to calculate distance from the intensity is &amp;lt;math&amp;gt;d=I/395&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Varying Horizontal Position.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Second Experiment: &amp;#039;&amp;#039;&amp;#039;The phototransistor is placed directly adjacent to the laser. The finger was placed at fixed distances from the laser (1 cm, 2.5 cm, 5 cm) and then moved horizontally (left/right in Experimental Setup above). Using 19.5 K-Ohm resistor.&lt;br /&gt;
&lt;br /&gt;
Note: The negative values are on the same side of the laser as the phototransistor. This results in a shorter distance for the light to travel and a greater intensity on the left side. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Varying Phototransistor Position.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Third Experiment: &amp;#039;&amp;#039;&amp;#039;The phototransistor was moved directly out into the sheet of light (up/down in Experimental Setup). The finger was moved in same up/down direction. Using 19.5 K-Ohm resistor.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:Varying Phototransistor Position Horizontally.jpg|thumb|left|300px|Click to Enlarge]]&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Fourth Experiment: &amp;#039;&amp;#039;&amp;#039;The phototransistor was moved to the left of the laser. The finger was moved in the up/down direction. Using 19.5 K-Ohm Resistor.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Limitations and Environmental Factors ==&lt;br /&gt;
&lt;br /&gt;
There were a few environmental factors that affect the sensors:&lt;br /&gt;
&lt;br /&gt;
1) Ambient light: The overhead light saturated the phototransistor and so the laser was pulsed (the pic was programmed to strobe the laser) in an effort to provide a noticeable difference between the ambient and laser light. As noted above, a finger in front of the transistor cast a shadow which had a larger effect (due to the blocking of the ambient light)than the actual blocking of the laser. Be aware that as the experiment is done any shadow cast on the sensors by a finger or body part will affect the ambient light sensed by the phototransistor and should be taken into account.&lt;br /&gt;
&lt;br /&gt;
2) Lower resistances can be used for the phototransistor to prevent saturation but this also causes a reduced sensitivity to light.&lt;br /&gt;
&lt;br /&gt;
3) The sheet laser provided was not uniform. There were different intensities of light across the line emitted. &lt;br /&gt;
&lt;br /&gt;
4) There is a limited range in which the fingertip laser light sensor is accurate. Using the code and setup described above, there was accurate sensing of the fingertip directly in front of the laser and phototransistor to about seven centimeters.&lt;br /&gt;
&lt;br /&gt;
5) The same finger and the fingernail side were used for all of the experiments. Results may be affected by testing with different fingers or whether it is the fingernail side or not, or a side of the finger. Instead of a finger, a white plastic dowel could be used as a control initially and then a finger used with more progress.&lt;/div&gt;</summary>
		<author><name>John Rula</name></author>
	</entry>
</feed>